In today’s fast-evolving world, saving time is essential, and Google authentication helps achieve that. With just one click, you can sign in to any website that uses Google authentication. This comprehensive article will guide you through the steps to incorporate this feature into your Ruby on Rails application.
This is a tutorial for advanced Ruby on Rails developers. We also assume that you have all the prerequisites installed. These include
Ruby and Ruby on Rails.
You can install Ruby using an easy all-plugins manager called ASDF, I use it to manage all my plugins and it comes in so handy trust me, It saves me the hassles and the bassles of having to use many other different managers for different plugins I am sure you may wanna try it out, check out the asdf-vm.com.
Let's kick off by creating a Ruby on Rails app, assuming you don't have one.
rails new <app name> --database=postgresql
Let's now add the devise gem. You can use this link or add it manually using
bundle add device
At this point, we have all our requirements ready. Now we can start the feature we are looking at today.
Step 1. Add the required Gems
In your newly created or existing(best practice is to start this new work in a new branch, this is my way, you could do it your way) Ruby on Rails app, add the following gems in your Rails app in the Gemfile:
Now we need to add two fields, `uid` and `provider`, to our Devise model (in my case, the User model).
`uid` (User ID): This field stores a unique identifier for the user's account provided by the OAuth provider (in this case, Google). Each user receives a distinct `uid` from the provider, enabling your application to identify them uniquely.
`provider`: This field indicates the name of the OAuth provider used for authentication (e.g., "google_oauth2"). It helps distinguish between different authentication methods and allows your application to support multiple providers if necessary.
Now, let's generate the migration:
rails g migration AddFieldstoUser provider
Add the below code to your migration:
def change
change_table :users, bulk: true do |t|
t.string :provider
t.string :uid
end
end
then run rails db:migrate to add these two fields in your user's table.
Now, add the below code to your devise model. Mine in user.rb:
Explanation Method Definition:self.from_google(u) defines a class method named from_google that takes a single argument u. This argument is expected to be a hash containing user data from Google.
create_with: This is a method provided by ActiveRecord that allows you to create a new instance of the model with predefined attributes. In this case, it sets: uid: u[:uid]: The unique identifier from Google for the user.
provider: 'google': Specifies that the user was authenticated via Google.
password: Devise.friendly_token[0, 20]: Generates a random password (using Devise's helper) for the user, which is not needed for social authentication but is required by Devise.
find_or_create_by!: This method attempts to find a record with the specified email in the database (the email comes from the u hash). If it does not find a match, it creates a new record with the provided attributes. The exclamation mark (!) at the end means it will raise an error if the record cannot be created.
Step 3: Configure Controller
Create a users/omniauth_callbacks_controller.rb file inside the controller's directory and paste the below code:
# app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
user = User.from_google(from_google_params)
if user.present?
sign_out_all_scopes
flash[:notice] = 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
def from_google_params
@from_google_params ||= {
uid: auth.uid,
email: auth.info.email
}
end
def auth
@auth ||= request.env['omniauth.auth']
end
end
In a nutshell: Class Definition: The Users::OmniauthCallbacksController inherits from Devise::OmniauthCallbacksController, allowing it to utilize Devise’s built-in functionality for handling OAuth callbacks.
google_oauth2 Method: This method is called when a user authenticates with Google. It attempts to create or find a user via the User.from_google(from_google_params) method, using parameters extracted from the Google auth information. If a user is found (user.present?), the following occurs:All previous sessions are signed out (sign_out_all_scopes). A success message is set in the flash (flash[:notice]). The user is signed in and redirected to their desired resource (sign_in_and_redirect). If no user is found, a failure alert is set in the flash (flash[:alert]), indicating the user's email is not authorized, and the user is redirected to the login page (redirect_to new_user_session_path).
from_google_params Method: This method constructs a hash with data obtained from Google's OAuth response. It stores the uid (unique identifier) and email of the authenticated user for further processing. The method uses memoization (@from_google_params ||=) to prevent re-evaluating the hash during the request.
auth Method: This method retrieves the authentication data from the request.env['omniauth.auth'] object, which contains information returned by Google after authentication. Similar to from_google_params, this method uses memoization to store the authentication data for later use.
Visit the Google API Console and create a new project as below: You can give any name to your project. I named it Google Authentication. After entering the name click Create. And then go into your google login project. There will be a dropdown in the navbar (i've showed it in the first picture), you can use it to change your project.
Go to the OAuth consent screen
Choose user type External
Click Create
Fill all the fields
Scroll down click Save and continue.
Next follow the below steps:
Select Application Type Web application
Enter any name
Go to your console/terminal and type the command rails routes | grep /callback. Copy the URL...
Go to your browser and click on Add URI button
Paste the copied url in URL field such as http://localhost:3000/user/auth/google_oauth2/callback
Click Create
Once you have created the project, a popup will display your client ID and client secret. Make sure to save this information for future use. Now that you have obtained your client ID and client secret, let's proceed with the configuration of Google login in your Rails app.
Step 6: Implement Google Login
Open up config/initializers/devise.rb file and paste the below code:
# config/initializers/devise.rb
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
config.omniauth :google_oauth2,
'GOOGLE_OAUTH_CLIENT_ID',
'GOOGLE_OAUTH_CLIENT_SECRET'