Login with Google - Rails 6 Devise edition

Category: Ruby :: Published at: 27.05.2022

Today i will try to share with you my experience about signing in with Google on Rails application.

For this tutorial i will use Rails 6.1 with devise gem.

Without the big beginning, let's get into our tutorial.

  • At first we should install all the needed gems inside our application:
gem "devise" # concider to use the newest version - 4.8.1 at the point of writing this tutorial
gem "dotenv-rails", groups: [:development, :test]
gem "omniauth"
gem "omniauth-google-oauth2"
gem "omniauth-rails_csrf_protection"

 

  • Then we need to generate devise configuration
rails generate devise:install

also let's create an User model which will keep our users

rails generate devise user

then, we need to add configuration inside our user model. Inside the models/user.rb file you will find attached modules.

Let's add the next one for our omniauth authorization:

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :omniauthable, omniauth_providers: [:google_oauth2] # added module

Next step is to add the uid column to the users table. You can add it to the existing (but not migrated) migration file, or just add the new migration:

rails g migration add_uid_to_users uid:string

Then you just need to migrate your data to the database:

rails db:migrate

 

  • Now we should focus on routing aspect. Devise generator should add one line of code to our config/routes.rb file.
devise_for :users

We need to create now some custom paths to work with controllers (it won't work by default)

  devise_for :users, controllers: {
    registrations: "users/registrations",
    sessions: "users/sessions",
    omniauth_callbacks: "users/omniauth_callbacks"
  }

Let's use another devise generator which will create files inside our app/controllers folder.

rails generate devise:controllers users

Created files should be matched now with with a routes, we've just created.

 

  • So we have now our routes, and controllers working under them. It is necessary to modify the actions there, as without it our login system will struggle a lot. Let's got inside our omniauth_callbacks_controller. We need to create an action, where google will redirect after successful or unsuccessful login processing.
  def google_oauth2
    user = User.from_omniauth(auth)

    if user.present?
      sign_out_all_scopes
      flash[:success] = t 'devise.omniauth_callbacks.success', kind: 'Google'
      sign_in_and_redirect user, event: :authentication
    else
      flash[:alert] =
        t 'devise.omniauth_callbacks.failure', kind: 'Google', reason: "#{auth.info.email} is not authorized."
      redirect_to new_user_session_path
    end
  end

This method will look for a user. If it matches the data, it will sign in and redirect us to the right route. If it fails, it will redirect us to the new_user_sesson_path.

As for now, we of course don't have from_omniauth scope yet. We need to create it inside our user model.

  def self.from_omniauth(auth)
    where(uid: auth.uid).first_or_create do |user|
      user.email = auth.info.email
      user.password = Devise.friendly_token[0, 20]
    end
  end

This will try to look for a user where email and password are matched. If it doesn't find any record, it will create new one.

 

  • Inside the config/initializers/devise.rb file we can find a commented section called OmniAuth with some example of omniauth github configuration. We should add our omniauth confguration under those lines:
config.omniauth :google_oauth2, ENV["GOOGLE_CLIENT_ID"], ENV["GOOGLE_CLIENT_SECRET"], {}

As you can see, we have created new environmental variables. There are plenty ways to use them - we have installed dotenv-rails gem on
development and we will use it to store the data inside it. Let's create .env file and paste there tho variables:

GOOGLE_CLIENT_ID=your_client_token
GOOGLE_CLIENT_SECRET=your_client_secret

After restarting our application, environmental variables we've just created should work and be accessable in any place of our app.

  • But of course your_client_token and your_client_secret are not the correct data to use with our system. We need to create new OAuth API credentials. Just go to the website below.

https://console.cloud.google.com/

When you paste your data inside .env file and restart the application - your login with google with google system should work :)

 


- Click if you liked this article

Views: 261