3
from rauth import OAuth1Service

OAUTH_REQUEST = "https://bitbucket.org/!api/1.0/oauth/request_token"
OAUTH_AUTH = "https://bitbucket.org/!api/1.0/oauth/authenticate"
OAUTH_ACCESS = "https://bitbucket.org/!api/1.0/oauth/access_token"

service = OAuth1Service(
           name='test',
           consumer_key='xxxxxxxxxxxxxx',
           consumer_secret='xxxxxxxxxxxxxxxxxxxx',
           request_token_url=OAUTH_REQUEST,
           access_token_url=OAUTH_ACCESS,
           authorize_url=OAUTH_AUTH)

resp = service.get_raw_request_token()
print resp

I went on Bitbucket and generated a consumer key-pair, but the response was 400. Any idea what's going on?

I looked at the Bitbucket doc and the URL are correct.


edit

Thank you to @maxcountryman for taking his time here.

I just read his linkedlin example code:

import os
from rauth import OAuth1Service

OAUTH_REQUEST = "https://bitbucket.org/!api/1.0/oauth/request_token"
OAUTH_AUTH = "https://bitbucket.org/!api/1.0/oauth/authenticate"
OAUTH_ACCESS = "https://bitbucket.org/!api/1.0/oauth/access_token"

service = OAuth1Service(
           name='test',
           consumer_key='blah',
           consumer_secret='blah',
           request_token_url=OAUTH_REQUEST,
           access_token_url=OAUTH_ACCESS,
           authorize_url=OAUTH_AUTH)

# You can run python -m SimpleHTTPServer if you want a local callback
rtoken, rtoken_secret = service.get_request_token(params={'oauth_callback': 'http://localhost:8000'})

authorize_url = service.get_authorize_url(rtoken)
print 'Visit this URL in your browser: ' + authorize_url
pin = raw_input('Enter PIN from browser: ')
session = service.get_auth_session(rtoken,
                                   rtoken_secret,
                                   data={'oauth_verifier': pin})

reponame = raw_input('Enter the reponame: ')
new_name = raw_input('Enter a new repo name: ')
account_name = raw_input('Enter your account name: ')
url = 'https://api.bitbucket.org/1.0/repositories/%s/%s' %(account_name, reponame)
r = session.put(url, data={'name': new_name})
print r

Example:

(k)yeukhon@yeukhon-P5E-VM-DO:/tmp$ python bb2.py
Visit this URL in your browser: https://bitbucket.org/!api/1.0/oauth/authenticate?oauth_token=xxxxxxxxxxxxx
Enter PIN from browser: 216000000
Enter the reponame: newpatch
Enter a new repo name: junk-patch
Enter your account name: yeukhon
<Response [200]>

edit take additional advice from max using base_url.

OAUTH_REQUEST = "https://bitbucket.org/!api/1.0/oauth/request_token"
OAUTH_AUTH = "https://bitbucket.org/!api/1.0/oauth/authenticate"
OAUTH_ACCESS = "https://bitbucket.org/!api/1.0/oauth/access_token"

service = OAuth1Service(
           name='test',
           consumer_key='blah',
           consumer_secret='blah',
           request_token_url=OAUTH_REQUEST,
           access_token_url=OAUTH_ACCESS,
           authorize_url=OAUTH_AUTH,
           base_url='https://api.bitbucket.org/1.0/')

# You can run python -m SimpleHTTPServer if you want a local callback
rtoken, rtoken_secret = service.get_request_token(params={'oauth_callback': 'http://localhost:8000'})

authorize_url = service.get_authorize_url(rtoken)
print 'Visit this URL in your browser: ' + authorize_url
pin = raw_input('Enter PIN from browser: ')
session = service.get_auth_session(rtoken,
                                   rtoken_secret,
                                   data={'oauth_verifier': pin})

reponame = raw_input('Enter the reponame: ')
new_name = raw_input('Enter a new repo name: ')
account_name = raw_input('Enter your account name: ')
url = 'repositories/%s/%s' %(account_name, reponame)
r = session.put(url, data={'name': new_name})
print r.text
print r
CppLearner
  • 16,273
  • 32
  • 108
  • 163
  • 1
    Just FYI, if a provider provides a consistent "base" URI from which to make API calls from, you can simplify your code by passing `base_url=https://api.bitbucket.org/1.0/` to the service constructor. Then you can make calls like this: `session.get('user')`, so `session.put('https://api.bitbucket.org/1.0/repositories...', ...)` might become `session.put('{0}/{1}'.format(account_name, reponame), ...)`. – maxcountryman Mar 29 '13 at 01:40
  • @maxcountryman Very interesting. Thank you very much! Just tried. :) – CppLearner Mar 30 '13 at 01:13

1 Answers1

5

You need to give the API an oauth_callback, like so:

r = service.get_raw_request_token(params={'oauth_callback': 'http://example.com/'})

That should get you back a proper response from the provider.

maxcountryman
  • 1,562
  • 1
  • 24
  • 51
  • I will try that in a few minute. But does this call_back has any meaning? Sorry but thanks a lot! – CppLearner Mar 28 '13 at 22:10
  • Yes, `oauth_callback` is a spec'd part of the authentication flow for OAuth; it's where the provider will redirect to after the user authenticates. Previously we had interpolated this parameter for you automatically, but given the variations between providers and differences in spec'd authentication flows, we decided to take this out and leave it up to the client. Do make sure you're using rauth 0.5.3 and Requests 1.1.0. I can provide a BitBucket example if you're unable to get it working. – maxcountryman Mar 28 '13 at 22:12
  • Wow. Thanks a lot. Answer by the author of ``rauth`` is an honor :) Just a few rookie questions. (1) I get back the confirmation ``oauth_token_secret=blah&oauth_token=blah&oauth_callback_confirmed=true`` and if I were correct I had to ask user to give permission to me. I see example code requests some pins that users have to type it in. Generally websites do this by redirecting to a dialog box. I am running an API web service. So is there a way that the user can give us the permission as soon as they fire the request to our application? What's the best solution? thanks. – CppLearner Mar 28 '13 at 22:30
  • Generally, you don't need a pin. That's being used for so called "out of band" authentication. Usually you'd just redirect back to your application after the user authorizes you (this is the dialog box). Then you make a request for an access token with the request token pair. After that point you're good to go. Regardless, you are going to have to ask the user to authorize your application, I'm not sure you can eliminate the dialog box if that's your goal? – maxcountryman Mar 28 '13 at 22:53
  • Yeah end goal is to autotmate that on behalf of the user. Now that I think about it more, automating it doesn't really make sense. I should use HATEOS concept in REST to make transition and expect user to give me the pin. But I want to share something quickly: I got the url but feed to ``requests.get`` will treat it as a regular url. I can run ``python -m SimpleHTTPServer``, use localhost:800 as callback and open the link in my chrome. I can get the pin number. – CppLearner Mar 28 '13 at 23:29
  • In any case, I am okay. I am going to post my Bitbucket code in a moment. Thanks! – CppLearner Mar 28 '13 at 23:30