Implementing Facebook authentication with Devise for your Rails 6 app

Mbonu Blessing - Aug 21 '20 - - Dev Community

Hello everyone,

This week, I will be writing about how to setup Facebook authentication for your Rails app.

Prerequisites

  • An app using Rails 6 with devise setup for authentication
  • A working knowledge of creating a new Rails app
  • A working knowledge of devise for authentication
  • An active Facebook account

Facebook Authentication

To implement Facebook auth, we need to create an app on Facebook that will generate an APP_ID and APP_SECRET for setting up devise omniauth later.

Create Facebook app

  • Go to https://developers.facebook.com/
  • Click on My Apps in the navbar
  • Click on Add a new App Alt Text
  • On the modal that pops up, select the For Everything Else option. Alt Text
  • Next, add your App Display Name and click the Create App Id button Alt Text
  • Complete the security check and this should redirect you to the app Alt Text
  • On the sidebar, click on Setting and then click on Basic. You should be able to see your APP_ID and APP_SECRET. Copy and save for later. Alt Text
  • In the App domains, add localhost. You can also add your add icon if you have one. Alt Text
  • Scroll down to the end of the page and click on the Add Platform Alt Text
  • On the modal that pops up, select Website Alt Text
  • Add http://localhost Alt Text
  • Save your changes

Setup Facebook Auth in devise

In this section, we will be setting up facebook auth in our rails app.

  • Add the omniauth-facebook gem to your gemfile
gem 'omniauth-facebook'
  • Run bundle install
  • Next we create a migration to add provider and uid to the user model. This stores the provider the user uses to register whether its facebook or google.
$ rails g migration AddOmniauthToUsers provider:string uid:string
  • Run rake db:migrate
  • Next, we need to update the devise initializer file to include the APP_ID and APP_SECRET we saved for later
# config/initializers/devise.rb
config.omniauth :facebook, "APP_ID", "APP_SECRET"

Note: If you chose to use the credentials to save your environment variables. You can use this command to edit it in your code editor. Run this code in your terminal. Change code part to your code editor if you don't use vscode.

$ `EDITOR="code --wait" bin/rails credentials:edit`

In the decrypted credential file, add the app_id and app_secret

facebook:
  APP_ID: '<facebook_app_id>'
  APP_SECRET: '<facebook_app_secret>'

So your initializer file update will be

config.omniauth :facebook, Rails.application.credentials.facebook[:APP_ID], Rails.application.credentials.facebook[:APP_SECRET], token_params: { parse: :json }
  • Next we need to make the user model omniauthable. Add this to the user model
# app/models/user.rb
devise :omniauthable, omniauth_providers: %i[facebook]
  • Next, we create an omniauth controller in a user folder to respond to facebook authentication.
# app/controllers/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 #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

  def failure
    redirect_to root_path
  end
end
  • Next, we go back to the user model to add the from_omniauth self method. This method finds or creates a new user when they register. The name_split part of for those that store the first_name and last_name of their users.
# app/models/user.rb
def self.from_omniauth(auth)
  name_split = auth.info.name.split(" ")
  user = User.where(email: auth.info.email).first
  user ||= User.create!(provider: auth.provider, uid: auth.uid, last_name: name_split[0], first_name: name_split[1], email: auth.info.email, password: Devise.friendly_token[0, 20])
    user
end
  • Next, we update the routes file for include the new controller we just added
# config/routes.rb
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
  • Finally, we add the facebook button to our view using a facebook path provided by devise. You can use this same path for both registration and login. You just need to update the button description.
<%= link_to "Register with Facebook", user_facebook_omniauth_authorize_path %>

And that should add facebook auth to your app.

Other Authentication

The process is quite similar for google authentication. We need to create a project for the app and then create the credentials for auth. I am going to attach a link to create credentials for google auth and the omniauth-google gem.

Create credentials on google
Omniauth Google gem
Omniauth twitter gem
Twitter guide for creating an app

Let me know what you think and what to write about in the comment section.

Until next week

. . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player