Guide for Integrating Omniauth in Rails 5 for Facebook Login Feature

In this classroom lecture, I teach how to integrate Facebook authentication into a Ruby on Rails 5 application.

Build out the basic application

  • Scaffold a basic application: rails new app_name -T --database=postgresql
  • Create a set of pages
  • Implement devise

Setup a Facebook developer account

  • Link to create the account
  • Make sure to list your site URL in the setting’s page, if only in development use something like http://localhost:3000

Integrate Omniauth

Add to your Gemfile

# Gemfile

gem 'omniauth-facebook'

Update the User Table with the params needed

rails g migration AddOmniauthToUsers provider:string uid:string name:string image:text
rails db:migrate

Update initializer

# config/initializers/devise.rb

config.omniauth :facebook, "App ID", "App Secret", callback_url: "http://localhost:3000/users/auth/facebook/callback"

Update the model

# app/models/user.rb

devise :omniauthable, :omniauth_providers => [:facebook]

Add a Link to Facebook

<!-- app/views/pages/home.html.erb -->

<% unless current_user %>
  <%= link_to "Sign in with Facebook", user_facebook_omniauth_authorize_path %>
<% else %>
  <%= link_to "Logout", destroy_user_session_path, method: :delete %>
<% end %>

Update Routes

# config/routes.rb

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

Create a users directory

mkdir app/controllers/users

Create a users controller

# app/controller/users/omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if @user.persisted?
      sign_in_and_redirect @user, :event => :authentication
      set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

  def failure
    redirect_to root_path
  end
end

Add custom methods to the User model

# app/models/user.rb

def self.new_with_session(params, session)
  super.tap do |user|
    if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
      user.email = data["email"] if user.email.blank?
    end
  end
end

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
  end
end

Application Source code: https://github.com/rails-camp/facebook-omniauth-demo

Jordan Hudgens

view all post
Leave a comment
Lucky one • 6 months ago

Amazing stuff here. Lucky me to comment first. And one advice for others - restart server after everything :D I struggled some time on this... :)))

reply
Jordan Hudgens • 6 months ago

Ha yes, anytime you make a code change outside of the app/ directory you need to restart the Rails server. I'm glad you found it helpful!

reply
Tiago Cássio • 4 months ago

There is any chance to reproduce this aproach with Rails 5 API? Thanks for this great article!

reply
Kampee • 3 months ago

i'm want a name from facebook login and then user input some data such as student_id, store in student table not user, How???

reply
AC • 2 months ago

Hey, thanks for this great resource. What should be put in the Valid OAuth redirect URIs and the Deauthorize Callback URL in the Facebook developer settings? I'm working on a app and the callbacks don't appear to be working properly.

reply

Please be polite. We appreciate that.

By Daniele Zedda • 18 February

← PREV POST

By Daniele Zedda • 18 February

NEXT POST → 34
Share on