Question

I'm trying to generate a request token using oauth2 in a Pyramid application for controlling access to an API I'm developing. I'm stuck trying to verify my consumer key and secret working from this example. On the Pyramid request_token endpoint I have the following:

@view_config(route_name = "api_request_token", request_method = "GET")
def api_request_token(request):
    auth_header = {}
    if ('Authorization' in request.headers):
        auth_header = {'Authorization': request.headers['Authorization']}

    req = oauth2.Request.from_request(
        request.method,
        request.url,
        headers = auth_header,
        query_string = request.query_string)

    try:
        oauth_server.verify_request(req, ConsumerKeySecret.getByConsumerKey(request.params.get('oauth_consumer_key')), None)
    except oauth2.Error, e:
        print e
    except KeyError, e:
        print e
    except Exception, e:
        print e

(ConsumerKeySecret.getByConsumerKey is a SQLAlchemy model classmethod that sets instance variables of key and secret for the given key.)

On the consumer side, again following the blog post mentioned earlier, I'm doing the following:

def build_request(url, method='GET'):
    params = {                                            
        'oauth_version': "1.0",
        'oauth_nonce': oauth2.generate_nonce(),
        'oauth_timestamp': int(time.time()),
        'oauth_signature_method': 'HMAC-SHA1',
    }
    consumer = oauth2.Consumer(key='b9085cb942dc427c92dd', secret='1735fd5b090381dcaf57')
    params['oauth_consumer_key'] = consumer.key
    req = oauth2.Request(method=method, url=url, parameters=params)
    signature_method = oauth2.SignatureMethod_HMAC_SHA1()
    req.sign_request(signature_method, consumer, None)
    return req

request = build_request("http://localhost:6543/api/01/request_token")
u = urllib2.urlopen(request.to_url())

The verification fails, however, with the following error:

Invalid signature. Expected signature base string: GET&http%3A%2F%2Flocalhost%3A6543%2Fapi%2F01%2Frequest_token&oauth_body_hash%3D2jmj7l5rSw0yVb%252FvlWAYkK%252FYBwk%253D%26oauth_body_hash%3D2jmj7l5rSw0yVb%252FvlWAYkK%252FYBwk%253D%26oauth_consumer_key%3Db9085cb942dc427c92dd%26oauth_consumer_key%3Db9085cb942dc427c92dd%26oauth_nonce%3D42023151%26oauth_nonce%3D42023151%26oauth_signature_method%3DHMAC-SHA1%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1310338562%26oauth_timestamp%3D1310338562%26oauth_version%3D1.0%26oauth_version%3D1.0

I'm confused here however as each query string parameter appears twice in the "expected" signature. What could be going wrong?

If that's an easy question to answer, I have a follow-up: once I've actually verified the request, how do I generate the request tokens? The oauth2 library is a little sketchy on documentation regarding this point, and most examples out there seem to be geared towards implementing consumers, rather then creating providers as well.

Thanks!

Update Responding to my own question to give what I think is an answer. From this bug report for oauth2, it would appear that the inclusion of the oauth_body_hash parameter was messing up my signature verification since I was using GET. Changing it to POST fixed the problem. Strange that this would occur anyway given that I'm also testing with this library.

And to answer the second part, I believe you can just generate any key/secret pair that is random and long enough. I've seen people split up sha1 hashes of some random source into two 20 character parts. You can then us oauth2.Token to automatically create the URL that you can then use in your authorize_token step.

Of course, if I'm wrong on any of this be sure to let me know.

Was it helpful?

Solution

This sounds exactly like a problem I ran into, but I came to a different (possible) solution.

It looks like all the query string parameters are being included twice, which is described in this bug report: https://github.com/simplegeo/python-oauth2/issues/21

Stripping the query string parameters as the issue described fixed it for me.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top