Google Authentication in Ruby On Rails
This article will show you how to allow your users to authenticate using Google. (UPDATED!)
Published on:June 9, 2016
This article shows you how to enable Google authentication for your Ruby on Rails application.
As mentioned in our Facebook Authentication in Ruby on Rails Guide, many developers find it convenient to utilize third party authentication services such as Facebook or Google instead of using their own login system. Using these services can be more sure and they also provide a better overall user experience.
Google App Setup
Before we can work on the actual code for authentication, we need to do some setup on the Google side of things.
First, sign into the Google APIs console at https://console.developers.google.com . Then click on the 'Select a project' dropdown in the upper right and click Create Project.
The create project modal will appear. Enter a project name and agree to the terms of service, then click 'Create'.
Next, do a search for contacts
then click on the Contacts API entry that pops up.
Click the blue enable button, then click the back button right next to it once it enables.
Now do another search for google+
and click the Google+ API entry that appears.
Click the enable button.
Now click the Credentials link on the left side of the screen.
Next, click Oauth Consent Screen, fill in the details, and click save.
Next click the blue button that says Create Credentials and choose OAuth client ID.
Choose Web application, enter http://localhost:3000/auth/google_oauth2/callback
, then hit create.
A box will pop up containing your credentials, copy them to a text file, you will need them later.
Now we are ready to build our Rails application!
Building the Rails Application
Now that we've set up things with Google, we need to add the code necessary to do the actual authentication. The best way to authenticate with Google is to use the omniauth-google_oauth2
gem. This gem allows you to quickly and easily add Google authentication, and it plays nice with all of the other omniauth gems. Add the gem to your gemfile.
gem "omniauth-google-oauth2", "~> 0.2.1"
Now run a bundle install
.
Next, we need to create an initializer. Create an initializer in the initializers folder called omniauth.rb
and add the code listed below. If you are editing an existing project that already uses omniauth you can just add the code below to your existing omniauth.rb
file. Make sure to replace my Google client id
with your Google client id, and my Google client secret
with your Google client secret.
OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, 'my Google client id', 'my Google client secret', {client_options: {ssl: {ca_file: Rails.root.join("cacert.pem").to_s}}}
end
On some systems, Rails is unable to find any cert files for SSL certificates. This presents a problem since the actual authentication is done via SSL. To resolve this, you will need to download this cert file and place it in the root directory of your Rails application making sure the file does not have a .txt extensionn on the end. You can also attempt to locate the directory on your own system and change the path listed in the omniauth initializer, but that is beyond the scope of this article.
Next, lets create a user model to store our user information. Run the commands below to create this now.
rails g model user provider uid name oauth_token oauth_expires_at:datetime
rake db:migrate
Now we need to create two controllers. The first controller, Home, is simply the landing page. The second controller, Sessions, will actually contain the logic that lets our users log in and out. Run the commands below to create these controllers.
rails g controller home show
rails g controller Sessions create destroy
Great! Now we need to set up a few routes. Modify your routes file so that it looks like the code listed below.
GoogleAuthExample::Application.routes.draw do
get 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', to: redirect('/')
get 'signout', to: 'sessions#destroy', as: 'signout'
resources :sessions, only: [:create, :destroy]
resource :home, only: [:show]
root to: "home#show"
end
The auth/:provider/callback
route actually handles the callback from Google back to omniauth. The auth/failure
route is used when an error occurs. The signout
route is used when the user clicks the log out button on your website. The rest of the routes just set up the controllers in your application and adds a site root.
The next thing we need to do is add some code to our User model. Open your users model and modify it so that it looks like the code listed below.
class User < ActiveRecord::Base
def self.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.name = auth.info.name
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
end
This code will take the data that Google returns and persist it to the database. If the user does not exist, a new one will be created, otherwise, the existing user will be updated.
Next, we will need to add some code to our application controller that will allow us to determine if the user is logged in or not. Open your application controller and modify it so that it looks like the code listed below.
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :current_user
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
The current_user function will check to see if the user_id exists in the session. If so it will return the current user. The helper method tells rails we wish to use this in our helpers and views as well.
Now, lets add some code to our sessions controller. This code tells rails how to return the callback that omniauth does. Open your Sessions controller and modify it so that it looks like the code listed below.
class SessionsController < ApplicationController
def create
user = User.from_omniauth(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
Next, lets modify our application layout and add a sign in/sign out link. Open your application layout and modify it so that it looks like the code listed below.
<!DOCTYPE html>
<html>
<head>
<title>Google Auth Example App</title>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
</head>
<body>
<div>
<% if current_user %>
Signed in as <strong><%= current_user.name %></strong>!
<%= link_to "Sign out", signout_path, id: "sign_out" %>
<% else %>
<%= link_to "Sign in with Google", "/auth/google_oauth2", id: "sign_in" %>
<% end %>
</div>
<div>
<%= yield %>
</div>
</body>
</html>
Now, if we start a rails development server and visit http://localhost:3000 we can try it out. Click the sign in link and you will be taking to a prompt that will ask you to sign in. Note that what you see below might vary slightly if you are already signed into your Google account.
Once you have signed in you will be prompted to allow the application to access your email address and basic information. Click accept and you will be signed into your app via Google.
That's it! You've successfully added Google Authentication for your app! Thanks for reading!