A Rubyist's Guide to the Twitter OAuth Dance

Twitter’s switchover to OAuth is complete, and developers are realizing what a huge pain in the ass it now is to authorize with the Twitter API. No doubt about it: OAuth is complicated. For developers who just want to quickly work with the Twitter API, the OAuth dance is tedious and complicated. Simple HTTP authentication with a username and password has been replaced with four steps:

  1. Register a Twitter application, which is an OAuth consumer
  2. Use the consumer key and secret to generate a request token and secret
  3. Use the request token and secret to generate an access token and secret
  4. Use the access token and secret to access the API

The problem with OAuth 1.x (OAuth 2.0 will solve these shortcomings) is that it’s geared towards the use case of external, user-centric applications. For a developer who wants to write a quick script to access the API, or integrate the API into an existing app, OAuth 1.x is overkill. There’s documentation from Twitter on all of this, but when I tried it out for myself the other night, it was an exercise in frustration, and I found myself following documentation from various places to get it working.

Registering the App

First, register an app, called a consumer in OAuth parlance, at dev.twitter.com/apps. I’m using a single “Utwilities” app for all my one-off uses of the API.

Utwilities

I’m not sure if creating one app for multiple uses violates the API terms of service, but I don’t want to go through the ceremony of registering a new consumer every time I want to use the Twitter API.

Skipping the Dance

Steps 2 to 4 outlined above are commonly referred to as the OAuth dance, where the consumer app generates a one-time request token that’s then used to generate the user-specific access token. The user-specific access token (and secret) is used in largely the same way as the username/password combination of that now bygone era. The great news is that Twitter lets us skip these steps by automatically generating an access token for the same user that registered the app. You can view your access token and secret in the sidebar of the app page:

Access Token

Things get really easy once you have the access token, especially with the Ruby Twitter gem. As documented, you’ll need to instantiate and authorize an OAuth client, then use that to instantiate a Twitter client.

require 'twitter'
oauth = Twitter::OAuth.new('consumer token', 'consumer secret')
oauth.authorize_from_access('access token', 'access secret')

client = Twitter::Base.new(oauth)
client.update('Tweeting with OAuth access!')

Joining the Dance

There will be times, however, when you need to authorize access to the consumer app for a Twitter user that isn’t the app owner. In that case, you’ll need to dance, and this is where things get hairy.

The important thing to know is that there are currently two ways a user can grant OAuth access. The first, and most popular, method is based on webpage redirects. You’ve gone through this process if you’ve ever authorized a third-party app that uses the Twitter API on your behalf. It’s great for end-users, but I won’t be covering that here.

The second method is better for developers: granting OAuth access when a web redirect isn’t possible or practical. This is necessary when generating a key as a developer – when the code will only be needing one access token and doesn’t need to support Twitter authorization for end-users. Authorization in this manner requires, believe it or not, a PIN number.

Using your app’s consumer key and secret, instantiate an OAuth client. Then ask for a request token.

oauth = Twitter::OAuth.new('consumer key', 'consumer secret')
request = oauth.request_token
request_token = request.token

Use the request_token to visit a URL that gives you back a PIN number:

https://twitter.com/oauth/authorize?oauth_token=REQUEST_TOKEN_HERE&oauth_callback=oob

When you open that URL in your browser, substituting the request_token appropriately, you’ll be asked to authorize and then will be presented with a PIN. You can now ask for an access token:

oauth.authorize_from_request(request.token, request.secret, 'THE_PIN_HERE')

# Save these to your database or keep in a config file
access_token = oauth.access_token.token
access_secret = oauth.access_token.secret

# Now you can use the client
client = Twitter::Base.new(oauth)
client.update('Tweeting after generating an OAuth PIN!')

OAuth 2.0

OAuth 2.0 promises a much easier workflow, but Twitter doesn’t support it yet. See Michael Bleigh’s slides from RailsConf for details. For now though, we have to dance.

blog comments powered by Disqus