[Rails] Setup OmniAuth Facebook

February 07, 2021

Introduction

OAuth 2.0 is the industry-standard protocol for authorization. OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications, desktop applications, mobile phones, and living room devices

Details from oauth website.

With Boring Generator

Boring Generator installation guide.

> rails generate boring:oauth:facebook:install # Facebook OAuth
> rails generate boring:oauth:github:install # Github OAuth

Without Boring Generator

1. Setup Devise

You need to ensure that devise is installed in-order to setup and use Devise Omniauth. To setup devise you could use the generator provided by Boring Generators or do it manually.

> rails generate boring:devise:install

2. Add Facebook OAuth gem

Add following Facebook OAuth gem in the Gemfile.

# for omniauth facebook
gem 'omniauth-facebook', '~> 8.0'

Similarly, you can add other OAuth provider gems. Example: Twitter, Google, GitHub. Boring Generator support some mostly used OAuth install generators.

3. Maintain OAuth Provider Details

Add the OAuth provider details in the User model to trace the user creation from OAuth easily.

> rails generate migration AddOmniauthToUsers provider:string uid:string
> rails db:migrate

4. Configure OAuth Devise Middleware

Add the Facebook OAuth devise middleware to handle the OAuth user registration.

# config/initializers/devise.rb
config.omniauth :facebook, "APP_ID", "APP_SECRET"

Each provider has different ways to register the application for OAuth. For Facebook, you can register application here: https://developers.facebook.com/apps/

5. Make User Omniauthable

Configure the auth strategy for devise User Model.

# app/models/user.rb
class User < ApplicationRecord
  # Similarly, for other OAuth change the provider name here.
  devise :omniauthable, omniauth_providers: %i[facebook]
end

6. Add Routes

Add the devise callback routes. When the authentication is successful, the provider would send the authenticated user details back on the callback routes.

Add following line to configure the callback action routes:

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

7. Add Callback Controller

Handle the omniauth callback controller for facebook. The callback controller would process the user data and create new user.

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  # See https://github.com/omniauth/omniauth/wiki/FAQ#rails-session-is-clobbered-after-callback-on-developer-strategy
  skip_before_action :verify_authenticity_token, only: :facebook

  def facebook
    # You need to implement the method below in your model (e.g. app/models/user.rb)
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if @user.persisted?
      sign_in_and_redirect @user, event: :authentication #this will throw if @user is not activated
      set_flash_message(:notice, :success, kind: "Facebook") if is_navigational_format?
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"].except(:extra) # Removing extra as it can overflow some session stores
      redirect_to new_user_registration_url
    end
  end
end

8. Process Omniauth Data

Add a class method in User model to process the OAuth data and create new user.

# app/models/user.rb
class User < ApplicationRecord
  ...

  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
      user.email = auth.info.email
      user.password = Devise.friendly_token[0, 20]
      user.name = auth.info.name   # assuming the user model has a name
      user.image = auth.info.image # assuming the user model has an image
      # If you are using confirmable and the provider(s) you use validate emails,
      # uncomment the line below to skip the confirmation emails.
      # user.skip_confirmation!
    end
  end
end

Happy Coding!!!