Alternative authentication process for your rails application using Omniauth and Devise

14 May 2013 by Ketan Deshmukh No comments

We are living in an era of web applications. Every day you come across new and innovative web applications. This brings to light a cut throat competition between them. Every application strives to attract as many users as possible. In this aspect it is very important to analyze – “Why will the users use your website and will continue to use it?”

Your application idea needs to be strong and path-breaking. However, having said so, it should also be simple to deal with real world problems. Although it seems easy to talk about, yet it is really difficult to find simple solutions for complex problems. Apart from the idea, technical ease of usage, online presence and solid marketing initiative for your app also matters when it comes to attracting users. How you implement your idea technically has got a big role to play in this.

What is Authentication process ?

In most of the user specific web application, the first step is Sign Up/Login process. Generally, the user doesn’t have access to all the services offered by the application unless he/she registers with the application. The registration is not necessary for all applications, but it is present in most of the cases.

Simplifying authentication!!

Entering your email address and a password into every website that you use can be time consuming. Worst case is remembering your login credentials for different web apps you use.

Here is a solution to ease your problem. OAuth allows you to authenticate against an OAuth provider. Rather than providing your username/email id and password to yet another site, you directly authenticate against a central provider. The central provider then supplies tokens for the different applications to read and/or write the user’s data on the application.

How OAuth works ??

Authentication Process

Figure 1

You need to register your application with service providers like Facebook/Twitter/Github in order to authenticate against these applications. Once you register, you’re given a unique key to identify your application and a secret passphrase, which is actually a hash. Neither of these should be shared. When your application makes a request to an OAuth provider, it will send these two parameters, along as part of the request so that the provider knows which application is connecting.

Figure 1 depicts the complete process elaborately. A user initiates the authentication process by clicking on the concerned service provider’s link that he wants to authenticate himself with. Your application then sends that unique key and that secret passphrase (given to you by the Service Provider when you register your application), and begins the authentication process by requesting a token ‘A‘. This token will be used as an identifier for this particular authentication request cycle. The provider then grants you this token and sends it back to your application. Your application then redirects the user to the provider ‘B‘ in order to gain the user’s permission for this application to access its data. When signing in with Twitter, your users would see something like following figure :

Twitter Aunthentication

Figure 2

Here user can either choose to authorize your application or cancel the process. If he chooses to authorize, your application has access to their data. If he clicks cancel, user will be redirected back to your application without granting the access to his data.

When user clicks on Authorise App ‘C‘,’D‘, he is then redirected to your application from the provider, with two parameters: an oauth_token and an oauth_verifier. The oauth_token is the request token you were granted at the beginning, and the oauth_verifier is a verifier of that token.

OmniAuth then uses these two pieces of information to gain an access tokenE‘,’F‘, which will allow your application to access the user’s data. There’s also additional data, such as the user’s attributes, that gets sent back here. The provider determines the extent of this additional data.

What is Omniauth and Devise?

Omniauth, as mentioned on its Github page, is a library that standardizes multi-provider authentication for web applications. This means that you can make your app authenticate through Twitter, Facebook, LinkedIn, Google Apps, GitHub, Foursquare, and more and have complete control from there. This page lists several gems available for different providers.

Railscasts for Omniauth : Part 1
Railscasts for Omniauth : Part 2

Devise is based on Warden. It is a complete authentication solution. Devise is a Rails Engine and it covers controllers and views as well. It allows you to have multiple roles (or models/scopes) signed in at the same time. Devise is modular and currently consists of eleven modules. Each of these modules provides a different aspect of authentication. For example, module Validatable provides validations of email and password.

Railscasts for Devise

Code implementation

To have a look at code implementation, we will consider “Twitter authentication” process. Add following gems to your gemfile :

gem 'omniauth'
gem 'omniauth-twitter'

Registering your application on twitter

You need to register your app on twitter before your users can use it to log in to your application. Registering with twitter gives you a consumer key and consumer secret for your application. These are used by twitter to identify your application when a user tries to use this service. This looks something like following image:
OAuth Setting

Setting up OmniAuth configuration

Callback URL in the above image is the URL to which twitter will send the response of the authentication process. This URL points back to your application. Next, tell OmniAuth about this provider. For a Rails app, your config/initializers/omniauth.rb file should look like this:

Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, "CONSUMER_KEY", "CONSUMER_SECRET"
end

Handling the response from your provider

When a user clicks the twitter button, your application will begin the OAuth process. To use OmniAuth, you need only to redirect users to /auth/:provider, where (:provider) is the name of the strategy (for example, facebook or twitter). From there, OmniAuth will take over and take the user through the necessary steps to authenticate them with the chosen strategy. After successful completion of the process, twitter sends back the user’s information response like this :

{
...
"extra" => {
...
"user_hash" => {
"id" => "14506011"
"screen_name" => "ketandeshmukh"
"name" => "Ketan Deshmukh”,
...
}
}
}

This is a very stripped-down version of the response. This response contains following important values:

  • Twitter provided ID of the user
  • Twitter username
  • Display name

Twitter doesn’t provide us with the email-id of the user. Hence in your application, if the user has authorized himself using twitter, you can use his twitter display name instead of his email id. Or, for such users, you can ask their email separately. This depends on the logic of your application.
To process the callback response, add following line to your routes.rb file :

match '/auth/:provider/callback', to: 'sessions#create'

Let’s see how the controller and model view looks like. The “create” method of your “sessions” controller( in this case ) will look something like this :

class SessionsController < ApplicationController
def create
@user = User.find_or_create_for_twitter(env["omniauth.auth"])
flash[:notice] = "Signed in with Twitter successfully."
sign_in_and_redirect @user, :event => :authentication
end
end

When a request is made to this action, the details for the user are accessible in the env["omniauth.auth"] key. env is the Rack environment of this request, which contains other helpful things such as the path of the request.

You then pass these details to a currently undefined method called find_or_create_for_twitter. It will deal with finding a User record for this information from Twitter, or creating one if it doesn’t already exist.

You then set a flash[:notice] telling the user they’ve signed in and use the Devise-provided sign_in_and_redirect method to redirect your user to the root_path of your application.

To make this action work, you need to define find_or_create_for_twitter in your User model. You can do this by using the code from the following listing. In your user model, i.e, in app/models/user.rb file :

def self.find_or_create_for_twitter(response)
data = response['extra']['user_hash']
if user = User.find_by_twitter_id(data["id"])         # Find user
user
else                                         # Create a user with
# a stub password.
user = User.new(:email => "twitter+#{data["id"]}@example.com",
:password => Devise.friendly_token[0,20])
user.twitter_id = data["id"]
user.twitter_screen_name = data["screen_name"]
user.twitter_display_name = data["display_name"]
user.confirm!
user
end
end

That’s it!!! You just need to write a migration for adding twitter_id, twitter_screen_name, twitter_display_name to your User model.

Conclusion

Here is a Summary of what we just did for your quick reference:

Now users are able to sign up and sign in by clicking the Twitter icon in your application rather than providing you with their email and password. The first time a user clicks this icon, they’ll be redirected off to Twitter, which will ask them to authorize your application to access their data. If they choose Allow, they will be redirected back to your application. With the parameters sent back from the final request, you’ll attempt to find a User record matching their Twitter ID or, if there isn’t one, you will create one instead. Then you’ll sign them in.

After that, when the user attempts to sign in using the Twitter icon, they’ll still be redirected back to Twitter, but this time Twitter won’t ask them for authorization again. Instead, Twitter will instantly redirect them back to your application; the whole process will seem pretty smooth, albeit with the delay that can normally be expected from doing two HTTP requests. Similarly you can use available OmniAuth strategies to add other providers like Facebook, Github to your application.

What are you waiting for now??? Start the rails server and test our Alternate authentication system!!

Ketan Deshmukh

Follow me on Twitter

Leave a Reply

Your email address will not be published. Required fields are marked *

Subscribe To Our Blog

Get access to proven marketing ideas, latest trends and best practices.

Next up home

Contact

Lets build cool stuff

Share your contact information & we will get in touch!

I want (Tell us more about your dream project)