Anything Geek Related


Python – 2 legged OAuth Woes

While I have been programming with Python I have found the following intricacies with the OAuth 2-legged approach, in regards to using web based APIs (all the examples are in Python & refer to the Vimeo API).

Note I don’t believe this is well documented, and have at times found the following confusing:

  1. When using Web based APIs, one does not need to be concerned about the concept of ‘tokens’ if you are using a 2-legged OAuth approach (even though alot of sites proclaim that one should always be requesting for tokens, and even the python OAuth APIs that exist in github.com don’t really indicate that one does not need tokens). This basically means you do not need a token if you are doing a HTTP ‘GET’ request (depending which web based API you are using).
  2. When using 2-legged OAuth (or 3-legged for that matter), you must indicate all the parameters that are going to be sent using the HTTP ‘GET’ request (equally this should apply for ‘POST’ requests as well) before you generate a ’signature method’.
  3. As of OAuth Standard 1.0a I believe there is a slightly broken nature in how OAuth is used and believe it is actually a flaw in the OAuth protocol, which I discovered by accident. When using a 2-legged approach (refer to example below), this method will ‘intermittently’ work, when I first tested this (using the vimeo API), it actually worked for the 1st iteration, but failed consecutively for 3 iterations before working again and then intermittently after that:
#Using Leah Culver’s Python library @ http://github.com/leah/python-oauth
#Note I have deliberately left out my API key and secret for the purposes of this blog post
VIMEO_API_URL = ‘http://vimeo.com/oauth/v2′
consumer = oauth.OAuthConsumer(VIMEO_API_KEY, VIMEO_API_SEC)
oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, http_url=VIMEO_API_URL)
oauth_request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1() , consumer, None)
#After I sign the request then I form the other parameters with the corresponding values:
http_request = ’http://vimeo.com/api/rest/v2?’ + ‘apiMethod’ + ‘param_value’ + str(oauth_request.to_postdata())

I originally thought it was a bug on the web API provider’s end, but it turned out to be a bug on how I perform the OAuth signing request. Basically, the bug was that I was signing the request before setting/applying the web API methods/parameter values I wanted (which obviously changed the hash of the signing request method). However, I believe that because it does not require a token, you can ‘brute force’ it to intermittently work if you call it enough times (possibly because the hash code for the request signature matches once in a while).

However, with a bit of help from using the php example provided by vimeo for their OAuth API, I figured out that one had to encode the parameters before signing the request:

consumer = oauth.OAuthConsumer(VIMEO_API_KEY, VIMEO_API_SEC)

oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, http_url=VIMEO_API_URL)

oauth_request.set_parameter(‘format’, ‘json’)

oauth_request.set_parameter(‘method’, ‘vimeo.videos.getByTag’)

oauth_request.set_parameter(‘tag’, tagname)

oauth_request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1() , consumer, None)

http_request = ‘http://vimeo.com/api/v2?’ + str(oauth_request.to_postdata())

Note: you could manually identify each OAuth required parameter without using the method: ‘from_consumer_and_token()’ but I found it easier to use it to save some code space (though I think the name is somewhat counterintuitive) as a non-token http url needs to be specified and is used for 2-legged OAuth.

Hope this helps anyone else who is trying to figure out how to use 2-legged OAuth (whether using Python or not) and is using examples from the web or from examples in an OAuth library, though I believe all examples I found only covered 3-legged approach, which requires an actual token request! I don’t believe a wrapper needs to be written for the 2-legged approach but there needs to be better examples to help facilitate developers understanding the 2-legged approach.