How to support Google OAuth authentication in Rails aplication

Create/Configure Google app

First, access this page:
https://console.developers.google.com/apis/dashboard

Create a new project:

Enter all information needed, then make sure enable Google+ APIs:

Click “ENABLE APIS AND SERVICES”, then enter “Google+” in the search box, you will see the “Google+ API” widget, click it.

Then, click “ENABLE”. Once enabled, click “Create credentials”:

Enter your project info, then click “Create OAuth client ID”

Configure consent page:

Click “Download” to download the json file containing clicent id and secret. The json file looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"web":{
"client_id":"YOUR_CLIENT_ID",
"project_id":"YOUR_PROJECT_ID",
"auth_uri":"https://accounts.google.com/o/oauth2/auth",
"token_uri":"https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
"client_secret":"YOUR_SECRET",
"redirect_uris":[
"http://localhost:3000/auth/google_oauth2/callback"
]
}
}

Create Rails application

Run the following command to create a Rails application:

1
rails new RailsGoogleOAuthTest

Add/configure omniauth-google-oauth2

Add the following into Gemfile:

1
gem 'omniauth-google-oauth2

Then run:

1
bundle install

Now create file config/initializers/omniauth.rb with the following content:

1
2
3
4
5
OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, "YOUR_GOOGLE_CLIENT_ID", "YOUR_GOOGLE_CLIENT_SECRET"
end

Create User model

1
2
rails g model User provider uid email first_name last_name picture oauth_token oauth_expires_at:datetime
rake db:migrate

Edit app/models/user.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class User < ApplicationRecord
def self.retrieve_user_info_from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.first_name = auth.info.first_name
user.last_name = auth.info.last_name
user.email = auth.info.email
user.picture = auth.info.image
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
end

Configure the Routes

Edit config/routes.rb:

1
2
3
4
5
6
7
8
9
10
11
Rails.application.routes.draw do
get 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', to: redirect('/')
get 'login', to: redirect('/auth/google_oauth2'), as: 'login'
get 'logout', to: 'sessions#destroy', as: 'logout'
get 'home', to: 'home#index'
root to: "home#index"
resources :sessions, only: [:create, :destroy]
resource :home, only: [:index]
end

Create/Edit controllers

Create Home and Sessions controller:

1
2
rails g controller Home index
rails g controller Sessions create destroy

app/controllers/sessions_controller.rb:

1
2
3
4
5
6
7
8
9
10
11
12
class SessionsController < ApplicationController
def create
user = User.retrieve_user_info_from_omniauth(request.env["omniauth.auth"])
session[:user_id] = user.id
redirect_to root_path
end
def destroy
session[:user_id] = nil
redirect_to root_path
end
end

app/controllers/home_controller.rb:

1
2
3
4
class HomeController < ApplicationController
def index
end
end

Edit app/controllers/application_controller.rb:

1
2
3
4
5
6
7
8
9
10
11
12
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :current_user
def authenticate
redirect_to :login unless user_signed_in?
end
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end

Edit pages

Edit app/views/layouts/application.html.erb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html>
<head>
<title>RailsGoogleOAuthTest</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<div>
<% if current_user %>
Signed in as <strong><%= current_user.first_name %> <%= current_user.last_name %></strong>!
<%= link_to "Sign out", logout_path, id: "sign_out" %>
<% else %>
<%= link_to "Sign in with Google", "/auth/google_oauth2", id: "sign_in" %>
<% end %>
</div>
<div>
<%= yield %>
</div>
</body>
</html>

Edit app/views/home/index.html.erb:

1
<h2>Welcome!</h2>

Test

Run your application:

1
rails s -b 0.0.0.0

Then access http://localhost:3000

Click “Sign in with Google”, you will be redirected to Google:

Authorize the access and you will be redirected back to your application

Share