Background:


Now a days, OAuth2 is quite popular. We are not going to in depth of how it’s work. We will develop application which will use devise and omniauth2 so, our application will have feature of signup using omniauth or devise.

Step 1: Create Account at Provider i.e. google


I am taking google as an example. or a full list of these providers, please check OmniAuth’s list of strategies . Go to google developer console and register our application. Google will authorise it next time when it will ask authentications using google. Click on create “OAuth consent screen” link and fill in require information. After saving go to “Credentials” link and click on “Create credentials”. It will have several options. Click on “OAuth client id”. Follow the instructions and you will have “Client ID” and “Client secrete” at the end. It will require while configuring devise.

Step 2: Install necessary gems.


Few gems will be needed to implement this feature. Lets add these to our Gemfile and run bundle command to install them.

  • gem 'devise'
  • gem 'devise-bootstrap-views'
  • gem 'omniauth'
  • gem 'omniauth-google-oauth2'

Step 3: Setup Devise


I am assuming that we know how to setup devise for authentication in rails app. Follow this to see how to setup devise.

Step 4: Integrate Omniauth2 with devise


For this we need to update our users table. We need to add the columns “provider” (string) and “uid” (string) to your User model.

rails g migration AddOmniauthToUsers provider:string uid:string
rake db:migrate

NOTE: we are using omniauth with devise hence no need to add provider middleware again in config/initializers/omniauth.rb

Now, declare the provider in your config/initializers/devise.rb.

config.omniauth :google_oauth2, "Client_ID", "Client_Secret", "callback_url"

Client_ID, Client_Secret and callback_url are generated in step1. callback_url may look like http://localhost:3000/users/auth/google_oauth2/callback.

This will configure our strategy, we need to make our model (e.g. app/models/user.rb) omniauthable:

devise :omniauthable, :omniauth_providers => [:google_oauth2]

we can add multiple providers. Now devise is already setup so it will create the following url methods:

  • user_omniauth_authorize_path(provider)
  • user_omniauth_callback_path(provider)

we can use this path methods to generate signin link i.e. <%= link_to “Sign in with Google+”, user_google_oauth2_omniauth_authorize_path %>.

By clicking on the above link, the user will be redirected to Google. (If this link doesn’t exist, try restarting the server.) After inserting their credentials, they will be redirected back to your application’s callback method. To implement a callback, the first step is to go back to our config/routes.rb file and tell Devise in which controller we will implement Omniauth callbacks:

devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }

Now add the file app/controllers/users/omniauth_callbacks_controller.rb and implemente callback as an action with the same name as the provider. Here is an example action for our google provider that we could add to our controller:

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def google_oauth2
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if @user.persisted?
      sign_in_and_redirect @user, :event => :authentication
      set_flash_message(:notice, :success, :kind => "Google") if is_navigational_format?
    else
      session["devise.data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

  def failure
    redirect_to root_path
  end
end

Here, all information retrieved from Google by OmniAuth is available as a hash at request.env[“omniauth.auth”]. Now, Implement from_omniauth method to our user model.

def self.from_omniauth(auth)
  where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
    user.email = auth.info.email
    user.password = Devise.friendly_token[0,20]
    user.name = auth.info.name   # assuming the user model has a name
    user.image = auth.info.image # assuming the user model has an image
    # If you are using confirmable and the provider(s) you use validate emails,
    # uncomment the line below to skip the confirmation emails.
    # user.skip_confirmation!
  end
end

This method tries to find an existing user by the provider and uid fields. If no user is found, a new one is created with a random password and some extra information.

Finally, if you want to allow your users to cancel sign up with Google, you can redirect them to cancel_user_registration_path. This will remove all session data starting with devise. and the new_with_session hook above will no longer be called.


devise_for :users, :controllers => {
  :omniauth_callbacks => "users/omniauth_callbacks" } do
    delete 'sign_out', :to => 'devise/sessions#destroy',
      :as => :destroy_user_session
end

You can find code here on GitHub

If you have queries then I will happy to help you out. Please reach me out at mayurt20@gmail.com

mayurkumar