In this tutorial, I'll implement google login in rails 7 using omniauth in devise gem.
Take note, in this tutorial I'll be using login-demo as code base which is tackled in this tutorial.
It's best to look at it before proceeding on this one.
I'll be assuming you implemented devise login in your rails app.
-
Add these gems.
gem "omniauth-google-oauth2" gem "omniauth-rails_csrf_protection"
-
Add this to your devise model(mine is
User
).
# models/user.rb :omniauthable, omniauth_providers: [:google_oauth2]
This would add the omniauth function of devise to the rails app.
-
Add fields to devise table.
class AddFieldsToUser < ActiveRecord::Migration[7.0] def change change_table :users, bulk: true do |t| t.string :provider t.string :uid end end end
Run
rails db:migrate
to add these fields to theusers
table.I'll be saving the uid and provider (which the value for this would be
google_oauth2
). Though it might change depending on the provider you're using. -
Create
omniauth_callbacks_controller.rb
.
# 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
-
Add this to your route.
# config/routes.rb Rails.application.routes.draw do devise_for :user, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' } # ------ # Other routes # ------ end
Google Oauth
In this part, things get a bit complicated.
In this, we would get the google client id, client secret and configure the google console to enable OAuth which would allow the rails app to log in using google.
Go to https://console.cloud.google.com. Then select a project but if not create one.
I named my newly created project Login Demo
.
Go to APIs & Services > Oauth consent screen
Choose user type External
. Next is to fill up the necessary input value on the form.
Click Save and Continue
at the bottom of the form.
Next is go to APIs & Services > Credentials
. At the top click CREATE CREDENTIALS
and choose OAuth client ID
.
Choose Web application
as Application type.
Check your routes and find the callback URL for google
Then add the callback URL to Authorized redirect URIs
.
Then click Create
. After creation, there should be a popup showing your client id and client secret. Save it for later use.
Now that you have your client id and client secret we're gonna start configuring google login in the rails app.
Implement Google Login
-
Add client id and client secret to your .env
# .env GOOGLE_OAUTH_CLIENT_ID='' GOOGLE_OAUTH_CLIENT_SECRET=''
-
Configure your devise.rb
# config/initializers/devise.rb config.omniauth :google_oauth2, ENV['GOOGLE_OAUTH_CLIENT_ID'], ENV['GOOGLE_OAUTH_CLIENT_SECRET']
-
Now just add the google log in button
// app/views/shared/_user_details.html.erb <%= button_to 'Login with Google', user_google_oauth2_omniauth_authorize_path, method: :post, :data => {turbo: "false"} %>
We have to create our custom link because the generated link for logging in with google may not work properly in rails 7.
Congratulations! 🎉 Now you have implemented google login to your rails 7 app.
You could check the repository here: https://github.com/jkevinbaluyot/login-demo/tree/omniauth-demo
References:
- https://www.reddit.com/r/rails/comments/twjznq/help_with_omniauth_and_devise_rails_7/
- https://dev.to/rbazinet/hotwire-fix-for-cors-error-when-using-omniauth-3k36
- https://medium.com/@adamlangsner/google-oauth-rails-5-using-devise-and-omniauth-1b7fa5f72c8e
EDIT: 06/25/2023
- I forgot to include this:
# app/models/user.rb
def self.from_google(email:, uid: )
find_or_create_by!(email: email, uid: uid, provider: 'google_oauth2')
end
Top comments (3)
Thanks for your tutorial
I just have an error with the controller:
NoMethodError in Users::OmniauthCallbacksController#google_oauth2
undefined method `from_google' for User:Class
Do you know where this error comes from?
Thanks
You need to define a
from_google
method in your model. I'm using the below method which works just fine.Heads up to the reader if you are using JS front end, you might have to add Authorized JavaScript origins in GCP