OmniAuth - thuy-econsys/rails_app GitHub Wiki

  • add gems

configure OmniAuth strategy for desired provider. be cognizant that setting config.omniauth in config/initializers/devise.rb will cause authentication to fail as they perform the same actions.

#config/initalizers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :google_oauth2, ENV['CLIENT_ID'], ENV['CLIENT_SECRET'], {
  scope: ['email',
    'https://www.googleapis.com/auth/gmail.modify'],
    access_type: 'offline'}
end

Controller

add action in omniauth_callback controller:

#app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  skip_before_action :verify_authenticity_token, only: :google_oauth2

  def google_oauth2
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if user.persisted?
      sign_out_all_scopes
      flash[:success] = 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."
      # session["devise.google_oauth2_data"] = request.env["omniauth.auth"].except(:extra) # Removing extra as it can overflow some session stores
      redirect_to(new_user_session_url)
    end
  end
  ...
end

request.env["omniauth.auth"]) retrieves OmniAuth data for the provider, available as a hash. auth.uid, auth.provider and auth.info.email will be used in the User model from_omniauth method.

Model

If you want to save your user to your User Database, add attributes for OmniAuth: provider, UID. Note this is optional as it's not necessary for authenticating.

rails g migration AddOmniauthToUsers provider:string uid:string:index
rails db:migrate

Create from_omniauth() referenced in controller above which will find an existing user by the provider and uid fields or otherwise create a new user:

class User < ApplicationRecord
  devise :registerable, :database_authenticatable,
        :recoverable, :rememberable, :validatable, :trackable,
        :omniauthable, omniauth_providers: [:google_oauth2]
...
  def self.from_omniauth(auth)
    where(email: auth.info.email).first_or_create do |user|
      user.email = auth.info.email
      user.password = Devise.friendly_token[0, 20]
    end
  end
  ...
end

routes

OmniAuth creates a route at localhost:3000/auth/<provider> which redirects to authentication provider which then redirects to app's callback URI, which responds with an access token. So add this to the route:

  devise_for :users, controllers: { omniauth_callbacks: "omniauth_callbacks" }

if not using Devise and wiring up your own sessions controller:

  post 'auth/:provider/callback', to: 'sessions#create'

make sure callback URI http://localhost:5000/auth/google_oauth2/callback correctly maps to it.

CAS

omniauth-cas is a developer created strategy for CAS provider based off of the official OmniAuth CAS strategy. See List of Provider Strategies.

OAuth/OpenID Authentication

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :cas, host: 'cas.yourdomain.com', url: 'yourdomain.com',
  fetch_raw_info: Proc.new { |strategy, opts, ticket, user_info, rawxml|
    return {} if user_info.empty? || rawxml.nil? # Auth failed

    extra_info = ExternalService.get(user_info[:user]).attributes
    extra_info.merge!({'roles' => rawxml.xpath('//cas:roles').map(&:text)})
    extra_info
  }
end

References

⚠️ **GitHub.com Fallback** ⚠️