This is part one of two posts I’m going to write about OAuth; the second will be somewhat more critical in tone. Before I criticize – and I know it’s hard to put together technologically things like OAuth – I want to actually accomplish something with it, so I at least I appear that I have somewhat of a clue about it. This is a report of what I’ve done.
bm_uri is a libary and tool I’ve written for working with URIs, and in particular http:// and https:// URLs. Here are some of the advantages of using bm_uri over all the normal Python urllib and urllib2 methods:
- downloads are cached; if a URL is temporarily not available,
bm_uri will return the cached version, likewise if it has been downloaded in the near past, the cached version will be returned rather than hitting the net again
- downloads can be cooked, meaning converted into a more useful form such as TIDY-cleaned up HTML, JSON, Unicode text and so forth
bm_uri handles all the protocol stuff for you (such as User-Agent, Last-Modified and so forth) so you don’t have to
- authentication is handled “invisibly” as possible for you … at least after the initial setup
Here is an example of accessing a OAuth resource using bm_uri returning my current location from Fire Eagle as a Python object. From a programming point of a view, I believe I have reduced this to close to the minimum number of steps possible. Here’s the setup phase:
import bm_uri
import bm_oauth
import pprint
bm_cfg.cfg.initialize()
bm_oauth.OAuth(service_name = "fireeagle")
Here’s using it in code – note how there’s no reference to OAuth here whatsoever.
loader = bm_uri.JSONLoader('https://fireeagle.yahooapis.com/api/0.1/user.json?format=json')
loader.Load()
pprint.pprint(loader.GetCooked())
And here’s the output of the program:
{u'stat': u'ok',
u'user': {u'location_hierarchy': [{u'best_guess': True,
u'geometry': {u'coordinates': [-79.418426513699998,
43.731891632100002],
u'type': u'Point'},
u'id': 572261,
u'label': None,
u'level': 1,
u'level_name': u'postal',
u'located_at': u'2008-03-19T04:09:30-07:00',
...
u'name': u'Canada',
u'normal_name': None,
u'place_id': u'EESRy8qbApgaeIkbsA',
u'woeid': 23424775}],
u'readable': True,
u'writable': False}}
Gather information
The devil is in the details, obviously and with OAuth, the little satan is doing the initial setup. Here’s how I did this for Fire Eagle – there’ll be something analogous for whatever service you are using:
- Log in or sign up (obviously)
- Go to the Developers’ Page
- Click on Create a New App
- Copy the “Consumer Key” and the “Consumer Secret” … these will be long-ish strings of nonsense
- Find out the Request Token URL, the Access Token URL, and the Authorization URL. These are public knowledge and for Fire Eagle are:
- https://fireeagle.yahooapis.com/oauth/request_token
- https://fireeagle.yahooapis.com/oauth/access_token
- http://fireeagle.yahoo.net/oauth/authorize
Note how Yahoo has conveniently made that last URL similar looking to the others, but not quite the same. Thanks!
However you implement OAuth, you’re probably going to need to be able to persist information to disk or database. As documented here several weeks ago, we already have that covered with our bm_cfg module. In ~/.cfg/fireeagle.json, create the following JSON format file:
{
"fireeagle": {
"api_uri" : "https://fireeagle.yahooapis.com/",
"oauth_access_token_url": "https://fireeagle.yahooapis.com/oauth/access_token",
"oauth_authorization_url": "http://fireeagle.yahoo.net/oauth/authorize",
"oauth_consumer_key": "ABCDEFGHIJKL",
"oauth_consumer_secret": "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345",
"oauth_token_url": "https://fireeagle.yahooapis.com/oauth/request_token",
}
}
The only new item here is the api_uri: that’s the prefix of URLs that bm_uri will use OAuth with.
Set it up
Next you have to do all sorts of OAuth stuff to actually work with OAuth. If the why interests you, please go read the spec! I’m more of how person myself, and this is what we need to do:
- run:
python bm_uri.py --service fireeagle --authorize
- this will pop up a browser window; grant your application access and then…
- run:
python bm_uri.py --service fireeagle --exchange
And that’s it – you should now be able to just work with the Fire Eagle API in bm_uri without even having to know OAuth is there!
End notes
- the current implementation only works with HTTP/REST GET; POST to come soon, DELETE and PUT as needed
bm_uri, bm_config and the rest of the code is freely licensed and available here. It is a constantly changing product, albeit converging on perfection in my own mind