Ruby on Rails Project: Using a Third-Party Authentication (OAuth)
Mar 25, 2019
It is exciting to see how far and how many things we can build at the end of the Rails section. For my Rails project, I kept working in the same domain from my Sinatra project. I continued my CMMS app for a chemical laboratory. It tracks all the equipment maintenances.
The main difference from the Sinatra to Rails implementation can be seen not only in the UI but in the fairly amount of logic in the backend. As I learned more about best practices and software design principles, I was able to come up with a much cleaner version. I could refactor it using helpers, partials with locals, and nested forms.
As the title suggests, one of the requirements for this project was to use a third-party authentication solution. For that, I found OmniAuth as a great library to handle different authentication providers like Google.
Google Authentication Setup
Here is a quick step-by-step, demonstrating how I set up my application. In addition to OmniAuth, I used another library called OmniAuth Google OAuth2. You can find the documentation here.
Gemfile
gem 'omniauth-google-oauth2'
gem 'dotenv-rails'
Google API Setup
Go to console developers and select your project if you have already set up one. Go to Credentials, then select the “OAuth consent screen” tab on top, and provide an ‘EMAIL ADDRESS’ and a ‘PRODUCT NAME’.
Because I didn’t know all details for creating a new project in Google Console, I followed this excellent blog post explaining how to create a Google API Console project and OAuth2 Client ID.
OmniAuth with Google
Create a file at config/initializers/omniauth.rb
with the following code:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET']
end
Environment Variables
Create a .env
file in your root application and include the ‘dotenv-rails’ library to load the config into the ENV hash. Don’t forget to add the .env
file to your .gitignore
to ensure you don’t commit your credentials. You don’t want to expose your credentials to strangers, right?
GOOGLE_CLIENT_ID="<paste your client_id keys here>"
GOOGLE_CLIENT_SECRET="<paste your client_secret here>"
Link to Login
If you have a navigation bar, create a link to login. In my case, I included the following link at app/views/layouts/application.html.erb
:
<%= link_to "Log in via Google", '/auth/google_oauth2', class: "btn btn-outline-secondary" %>
Routing OAuth Flow in Your Application
In my config/routes.rb
file:
get '/auth/google_oauth2/callback', to: 'sessions#create_from_omniauth'
User Sessions
In my app/models/user.rb
file, I included a method that finds or create new users from Google Authentication. It assigns them a random password if new.
def self.create_from_google(auth)
User.find_or_create_by(email: auth[:info][:email]) do |user|
user.username = auth[:info][:name]
user.password = SecureRandom.hex
end
end
In my app/controllers/sessions_controller.rb
:
def create_from_omniauth
@user = User.create_from_google(auth)
set_session
if logged_in?
flash[:message] = "Successfully authenticated via Google!"
redirect_to user_path(@user)
else
flash[:message] = "Something went wrong. Try again"
redirect_to root_path
end
end
private
def auth
request.env['omniauth.auth']
end
You can find the source code at maintenance_management_rails_app.