Authentication with OAuth in Ruby on Rails
Posted by Julien France on Mar 05, 2010
1) Why Using OAuth:
Have you ever built an application that needed access to user data from a third-party application like Google Apps, Twitter, Facebook, …? In the following post we will examine how to do this with Oauth and Google Apps
The easiest way would be to get the Google login and password of your users via a login form on your application. You would then be able to use these credentials to connect to the third-party application and get access to your users data.
The problem:
Are you sure your users will agree to provide their Google login and password to your application?
Imagine that you want to give 10 euros to a friend. Even if you trust this friend, you probably won't give him your credit card and password so he can connect to your bank account and take the 10 euros himself?
That means that your friend will have full access to your bank account and could take as much money as he want.
When you don’t want your friend to have access any longer to your bank account, you’ll have to change your password, which could be annoying.
That’s the same thing for your application using your user’s Google credentials. Your application would have full access to all your user’s Google data and the only way for the users to revoke that would be to change their Google password.
The OAuth solution:
OAuth is an authorization protocol that will redirect the user to the third-party application (in this case Google) where he will be informed that your application requests access to some of his Google service data. If the user wants to allow access, he’ll have to log into his account (still on the Google page) before being redirect back to your application. In the background Google will return an access token that your application will use to get access to the users data.
- No login-password information has been transferred to your application
- Your application only received access to a limited set of data.
- The user can revoke your applications access to his Google account via his Google account management page. (https://www.google.com/a/yourdomain.com/ManageAccount)
Given our previous bank example, this could be compared to a bank check of 10 euro that you would give to your friend. When he collects the check, he will receive 10 euro and that’s it. He also doesn’t know anything about your bank secret code.
2) The OAuth protocol in detail:
The OAuth protocol consists of a sequence of interactions between your application, Google services and the end user. The following diagram illustrates the sequence: (source: http://code.google.com/intl/fr/apis/accounts/docs/OAuth.html)
- The application contacts the Google Authorization service, asking for a request token for one or more Google service.
- Google responds with an unauthorized request token.
- The application directs the end user to a Google authorization page, referencing the unauthorized request token.
- On the Google authorization page, the user is prompted to log into their account and then either grant or deny limited access to their Google service data by the application.
- The user decides whether to grant or deny access to the application. If the user denies access, they are directed to a Google page and not back to the application.
- If the user grants access, the Authorization service redirects the user back to a page designated when the application was registered with Google. The redirect now includes the authorized request token.
- The application sends a request to the Google Authorization service to exchange the authorized request token for an access token.
- Google verifies the request and returns a valid access token.
- The application sends a request to the Google service in question. The request is signed and includes the access token.
- If the Google service recognizes the token, it supplies the requested data.
Note that we described the protocol with a Google example but the principle is similar for other third-party applications. We’ll not go in further detail on the explanation of this protocol but it may be interesting to give some more information on how to get the initial request token (first point of the above diagram).
The initial token request needs to contain the following information:
- OAuth_signature_method
- OAuth_signature
- OAuth_consumer_key
- OAuth_scope
- OAuth_callback
- (and other attributes that we’ll not detail in this post)
1) All requests sent via OAuth need to be signed. You then have to specify the method used to generate the signature. This method can either be ‘RSA-SHA1’, ‘HMAC-SHA1’ or ‘PLAINTEXT’ (not supported by Google).
2) The OAuth signature is constructed based on a private key (when using the ‘RSA-SHA1’ signature method) or based on a consumer-key and consumer-secret (when using the ‘HMAC-SHA1’ signature method)
3) The consumer-key is the Domain identifying your application. It is also used for building the signature.
4) The scope is a URL identifying the service you want to get access to. The token you receive at the end of this process only enables access to this given service.
5) The callback parameter is the URL the user will be redirected to after access to a Google service is granted.
You may wonder how to get the consumer-key and consumer-secret needed for building the signature. Actually, this information is generated during the registration of your application to Google.
The registration provides enhanced security for your users as Google recognizes your application as secure.
But what if you don’t want (or can’t) register your application to Google? No problem, in this case you’ll just have to use the ‘HMAC-SHA1’ signature method and use ‘anonymous’ for the consumer-key and consumer-secret attributes.
3) OAuth with Ruby and Rails:
Now that we have been introduced to the OAuth authorization protocol we can start implementing it in our applications.
Xaop works mainly with Ruby and Rails, so in the remainder we describe how to use OAuth in a Rails web application.
Implementing OAuth in your web application will be quite easy as there already exists a rails plugin for it. (http://github.com/pelle/oauth-plugin)
This plugin uses the OAuth ruby library (http://oauth.rubyforge.org/) so you'll need to install this library first:
sudo gem install oauth
Then you need to install the OAuh rails plugin:
sudo gem install oauth-plugin
The OAuth plugin contains a provider generator that can be used to make your application act as the service provider application (like Google in our example). In our case, we don’t want our application to be a provider but a consumer application that will request access to a Google service. We are not going to explain the provider part of the plugin here.
Let’s then use the OAuth consumer generator:
./script/generate oauth_consumer --haml
note the --haml optional parameter which causes the generated oauth views to be in .haml instead of .rhtml
A configuration file has been generated:
config/initializers/oauth_consumers.rb
Next we add the provider application information in this config file:
OAUTH_CREDENTIALS={
:google=>{
:key=>"anonymous",
:secret=>"anonymous"
:scope=>"https://www.google.com/calendar/feeds/",
:options => {:site => "http://www.google.com",
:request_token_path => "/accounts/OAuthGetRequestToken",
:access_token_path => "/accounts/OAuthGetAccessToken",
:authorize_path=> "/accounts/OAuthAuthorizeToken"}
}
}
You can see in the scope attribute that we want to connect to the Google calendar service.
The plugin creates a new model class that subclasses ConsumerToken for each of the provider site setup in the OAUTH_CREDENTIALS hash. In this case a GoogleToken model class is created on the fly.
Then you can add a has_one relation in your user model:
has_one :google, :class_name=>"GoogleToken", :dependent=>:destroy
It is now time to run the migration that has been created during the oauth-consumer generation.
rake db:migrate
Your application is now ready. When you want to request access to the Google service of the current_user (Google calendar in this example), you just have to redirect the user to the following location:
/oauth_consumers/[SERVICE_NAME]
In our case we replace ‘[SERVICE_NAME]’ by ‘google’
The user is then redirected to the Google authentication page. Once logged in, he is redirected to the call_back url. In the background the OAuth plugin has started the token exchange as described in section 2 of this post and has stored the authorized request-token in your database. You can access it via the ConsumerToken model.
As we said above, a Google model that subclasses ConsumerToken has been created and contains a belongs_to relation with the User model.
In your application you can access this request-token via a user object:
@user.google
But what we really need from our request to Google is the access_token. This can be retrieved by calling the ‘client’ method on the request_token object:
@access_token = @user.google.client
The client method will actually finish the OAuth token exchange with Google by exchanging the request_token with an access_token.
We are now ready to request user data from the Google calendar service. This can be done by sending an HTML request to the access_token object.
Example:
@access_token.get(‘http://www.google.com/calendar/feeds/default/allcalendars/full’)
This returns an XML response containing a list of all users’ calendars. You can use a calendar id or name from the list in a new request that returns the given calendar. After that you can request the entries of a given calendar and so on.
See the API directory of Google for more request examples: http://code.google.com/intl/fr/apis/gdata/docs/directory.html
I suggest using a ruby XML parser to process the OAuth XML response.
You're now ready to create your custom GoogleCalendar ruby library for OAuth, e.g., a Calendar class with for example the ‘entries’, ‘create_new’, ‘update_sharing’ methods.
I hope you’ll like using OAuth with ruby. Happy coding ;-)
blog comments powered by DisqusEntries per category
- 6 pages are tagged with docpublisher
- 11 pages are tagged with events
- 14 pages are tagged with rails
- 30 pages are tagged with ruby
- 7 pages are tagged with sharepoint

