OAuth Explained and What It Is Good For

OAuthTwitter recently announced OAuth support and that eventually they will be deprecating HTTP Basic Authentication in favor of OAuth. Knowing this, I figured it was about time to get familiar with OAuth and update the Twitter gem to use it.

Let me start by explaining my history with OAuth. I have none. There that was fast. I didn’t read the specifications or any articles on OAuth. I simply dove in code first and tried to figure out what was going on and how to make things work. I promise that what I’m about to explain will be simple and that I will not spend any time on hmac-sha1 signatures.

For the code examples below, I’ll be using the OAuth gem. Install is typical and I’ll provide it below for copy and paste.

sudo gem install oauth

Tokens and Secrets

At first, the hardest thing to figure out was all the tokens and secrets. Basically, there are three sets of made up of a token and a secret. Each set builds upon the last. The three sets are consumer, request and access.

The consumer token and secret are provided for you by the OAuth provider, when you register an application with them. These basically define what application is attempting to do the deed. You can create a new consumer like this:

consumer = OAuth::Consumer.new(
  'consumer token', 
  'consumer secret', 
  {:site => 'http://twitter.com'}
)

Before I go on, let me explain the end goal. The end goal with OAuth is to get an access token and secret. Once you have these, requesting a users information is much like it would be with HTTP Basic Authentication from a Ruby API point of view.

Request Token

In order to get the access token, you have to create a request token, keep track of it, and then redirect the user to the provider to authorize your application. You can create a new request token, using the consumer you just created, like so:

request_token = consumer.get_request_token
puts request_token.token, request_token.secret

The other thing that the request token provides is an authorization URL. The authorization URL is where your application redirects to, to allow the user to grant or deny you access to the their data. You can get the authorization URL in quite a predictable manner:

request_token.authorize_url

If you were using Rails, you would simple redirect to this URL. Before you redirect, be sure to store the request token and secret as you’ll need those to create the access token when the user returns to your application.

Whether your app is on the web or something else, the aforementioned steps are the same. The difference is if you have a web app, you provide a redirect URL that the provider sends the user back to upon granting access, whereas if you have a desktop app, or the like, the page will just inform the user to head back to the app.

Access Token

Either way, once the user is back at your app, you use the request token and secret to generate the access token. In the code below, you would use the request token and secret that you stored in the session before redirecting to the authorization URL.

request_token = OAuth::RequestToken.new(consumer, 'request token', 'request secret')
access_token = request_token.get_access_token

Once you have the access token, you can make authenticated requests like so:

puts access_token.get('/statuses/friends_timeline.json')

I haven’t had to go this far yet, but I’m assuming you would store the access token and secret in the database or something for later use. Someone correct me if I’m wrong about this. Next time you need to access the user’s data, you can simply create a new access token from the token and secret, and once again make authenticated requests.

access_token = OAuth::AccessToken.new(consumer, 'access token', 'access secret')
puts access_token.get('/statuses/friends_timeline.json')

The Twitter Gem

So how does all this affect the Twitter gem? Currently, setting up the authentication for the Twitter gem is as easy as this:

Twitter::Base.new('email', 'password')

In the OAuth version of the Twitter gem, setting up the authentication will be something like this:

Twitter::Base.new('access token', 'access secret')

So, pretty much the same. The only difference is that you will have to register your application with Twitter and then go through the process of getting the access token and secret. The good news is I already have a Twitter::OAuth class that will make this process as easy as possible.

What It Is Good For

I see three common methods for authenticating web services—HTTP Authentication, API keys and OAuth. HTTP Auth is simple, but then you end up with usernames and passwords all over the interwebs. OAuth is better in that users don’t give out passwords and can cancel at anytime with any app they have granted permission to.

The next question might be, “Wouldn’t an API key system be more simple than OAuth?” The answer is yes—for developers. For developers, it is easier to just tack an API key on every request than to go through the process of all the aforementioned tokens and secrets. So if an API key system is easier for developers, why use OAuth?

I see OAuth as the easiest solution for users. When determining how something will work for users, I often use the mom test. I guarantee you if my mom wanted to print a picture from flickr, she would not be able to figure out how to create an API key on Flickr and then use it with the printing site. Think about the opposite though. I definitely think that when redirected to flickr from the printing site, she could click yes to grant the printing site access.

OAuth is easier for users and API keys are easier for developers. When you go to build your API, take your primary audience into consideration and pick the solution that suites them best.

Hopefully this primer helps those (like me a day ago) who haven’t taken the time to get to know OAuth, and also those who have enjoyed the Twitter gem and are curious about what implications OAuth brings to the table. Formerly, I thought OAuth was over complicated, but now that I’ve spent a few hours with it, I’m pretty comfortable. Oh, and the other cool thing about this is now I have a base to work from for adding OAuth support to HTTParty.

Any OAuth junkies out there, feel free to correct me or elaborate in the comments.

Update: For more on OAuth, you can read how I updated the Twitter gem to use it.

Some Further Reading

5 Comments

  1. That’s pretty introduction, actually it’s far easier to grasp the principle than the official documentation.
    Thanks!

  2. nice article, i think a picture would have been helpful :)

  3. For anyone wanting to register their app as a client to twitter’s oauth server, my fork of John’s twitter gem (http://github.com/drnic/twitter/tree/master) has a “twitter register_oauth” command which logs in and submits the request for you, and returns the consumer key/secret to STDOUT.

  4. @khelll – Thanks. I guess everyone learns differently, but I felt the same way.

    @grosser – Thought about a picture, but I really try to make things work with words before adding a pic and by the time I was done writing I was too tired/lazy to make a graphic. I might update it with a graphic later.

    @Dr Nic – Cool. I’ll have to take a look at that when I get a moment.

  5. OAuth is really not a monster. Thanks!

Sorry, comments are closed for this article to ease the burden of pruning spam.

About

Authored by John Nunemaker (Noo-neh-maker), a web developer and programmer who has fallen deeply in love with Ruby. More about John.

Syndication

Feed IconRailsTips Articles - An assortment of howto's and thoughts on Ruby and Rails.

Feed IconRails Quick Tips - Ruby and Rails related links.