Rabid is now Ackama
In September 2018, on the company’s 8th birthday, Rabid became Ackama - this was to reflect that fact that we work on large digital ecosystems, and given that nature is the largest ecosystem in the world we wanted a name that came from nature. Ackama, or Makamaka, is a small bushy tree with white flowers and red seeds. It’s found on the coast from Whangarei north.
Using omniauth-google-oauth2 for Google OAuth2 with Ruby on Rails
I tried doing this manually using the oauth2
gem, but while it kind-of works, getting any sort of user information requires you to decode a JWT payload (ugh, OpenID why does Google no longer support you).
Instead I got it working with just the omniauth-google-oauth2
gem. Based on this tutorial which is for an older version of Rails:
1. Add new bundles and run bundle install
:
gem 'haml'
gem 'figaro'
gem 'omniauth-google-oauth2'
2. Create a new controller for sessions, and a new database model for users:
rails generate session_migration
rails generate controller sessions
rails generate model User provider:string uid:string name:string refresh_token:string access_token:string expires:timestamp
rake db:migrate
3. Configure the session to use a database rather than cookies which have a 4KB limit:
# config/initializers/session_store.rb
Example::Application.config.session_store :active_record_store
4. Create your SessionsController:
# /app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
def create
auth = request.env["omniauth.auth"]
user = User.where(:provider => auth["provider"], :uid => auth["uid"]).first_or_initialize(
:refresh_token => auth["credentials"]["refresh_token"],
:access_token => auth["credentials"]["token"],
:expires => auth["credentials"]["expires_at"],
:name => auth["info"]["name"],
)
url = session[:return_to] || root_path
session[:return_to] = nil
url = root_path if url.eql?('/logout')
if user.save
session[:user_id] = user.id
notice = "Signed in!"
logger.debug "URL to redirect to: #{url}"
redirect_to url, :notice => notice
else
raise "Failed to login"
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, :notice => "Signed out!"
end
end
5. Login to your Google Developers Console, create a new Project, and visit APIs & Auth:
- APIs: enable Contacts API and Google+ API, to prevent Access Not Configured. Please use Google Developers Console to activate the API for your project.
- Consent screen: make sure you have an email and product name specified
- Credentials: create a new Client ID of type web applicaton, setting your Redirect URI to http://localhost:3000/auth/google_login/callback
6. Edit config/application.yml
with these Google keys (figaro
will make all of these settings available through ENV[property]
):
# config/application.yml
OAUTH_CLIENT_ID: "<CLIENT_ID>"
OAUTH_CLIENT_SECRET: "<CLIENT_SECRET>"
APPLICATION_CONFIG_SECRET_TOKEN: "<A LONG SECRET>"
7. Enable Omniauth to use Googleauth2 as a provider (approval_prompt
must be an empty string otherwise it will force a prompt on every login):
# /config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2,
ENV['OAUTH_CLIENT_ID'],
ENV['OAUTH_CLIENT_SECRET'],
{name: "google_login", approval_prompt: ''}
end
8. Enable new routes:
# /config/routes.rb
Example::Application.routes.draw do
# ...
get "/auth/google_login/callback" => "sessions#create"
get "/signout" => "sessions#destroy", :as => :signout
end
9. Now finally, you can add login/logout links in your navigation template, or whatever:
/ /app/views/home/index.html.haml
%p
- if current_user
= link_to "Sign out", signout_path
= current_user.name
= current_user.inspect
- else
= link_to "Sign in with Google", "/auth/google_login"
10. Which uses a helper method, current_user
, which loads the User
model based on the session user_id
:
# /app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
# ...
helper_method :current_user
private
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end