How To Setup Devise and OmniAuth for Your Rails Application

The majority of Ruby on Rails applications require registration and authentication mechanisms, building them from scratch requires time effort and precision,  and if not done right it can expose your application to security breaches, thankfully there is Devise. This gem is so flexible and versatile that you can set up a really robust and powerful authentication system within minutes.

One great way to make our users love our applications it’s allowing them to access our application without creating a new account, honestly, that sucks! people don’t want to create more and more accounts, they already have too many.

social-1206610_1280

Omniauth allows you to easily integrate more than sixty authentication providers, including Facebook, Google, Twitter and GitHub. In this tutorial, I’m going to explain how to integrate these authentication providers into your app.

Step 1 – Create a New Rails App

For the purpose of this tutorial, we are going to call our new app omniapp. After creating the application, use cd to enter the application’s base directory.

rails new blogapp

cd blogapp

Note: All commands must be run from inside of your applications directory.

Step 2 – Add Gems to your Gemfile

As I mentioned before omniAuth supports several providers, for this exercise we are going to use one of the most popular ones, facebook, therefore we need to add  ‘omniauth-facebook’ gem to our gem file.

#Gemfile
gem 'devise'
gem 'omniauth-facebook'

You will need similar gems to support other providers. For example, to support Twitter, you will need omniauth-twitter.

Now run bundle install to install the new gems.

Step 3 – Add Functionality to your App

In order to test what we are doing, we will need to see if our app is working, so let’s add basic functionality to our blog app. We can use rails g scaffold for that.

Pro Tip: Try not to use rails g scaffold that much, since this generator may add things you dont really need and will make your app slower.

But to make our process faster let’s use it:

rails g scaffold Post title:string description:string

rake db:migrate

Let’s edit our routes  and add our root by going into /config/routes.rb.

Rails.application.routes.draw do
  resources :posts
  root 'posts#index'
end

Now you can start your development server by typing  rails s, and visit http://localhost:3000/ from your browser.

Feel free and add a couple of posts by clicking “New Post”, make sure your application is working. As you can see, no login is required yet, let’s fix that!

Step 4 – Configure Devise

Type the following commands to add Devise authentication support.

rails generate devise:install

rails generate devise User

rake de:migrate

This adds the sign-in and sign-up forms, and all the associated logic.

Now we have a basic authentication system, where users can register, and then log in. However, all the pages are still directly accessible. To change this, edit blogapp/app/controllers/application_controller.rb and add authenticate_user!  as an action that has to be performed before rendering any view.

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :authenticate_user!
end

You can register as a new user by visiting http//:localhost:3000/users/sign_up.

Go ahead and create one!

Step 5 – Add OmniAuth Capability to User Model

Add a new column called uid to the model that Devise generated.

rails g migration AddOmniauthToUsers provider:index uid:index

rake db:migrate

Step 6 – Add OmniAuth Configuration to initializer

Go into config/initializers/devise.rb and under the omniAuth section add:

config.omniauth :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET']

This requires that you have FACEBOOK_KEY and FACEBOOK_SECRET in your environment. Create an application in the facebook developer console and get these values from there.

You will be asked for a callback URL during the registration process, here you can add http://localhost:3000/users/auth/facebook/callback. This setting is listed under Client OAuth Settings in the dashboard.

Set the values in your shell like so,

export FACEBOOK_KEY=your_app_id

export FACEBOOK_SECRET=your_app_secret

Remember never to keep your API Keys visible in your application, it’s not safe, you can use different gems to protect them, I like to use figaro gem for that.

Step 7 – Enable a Route for Omniauth

Add this to routes.rb to tell create a route for Omniauth to send its authentication data to:

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

Step 8 – Enable Omniauth for User Model

Add this line to user.rb

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

We have to write a User.from_omniauth method ourselves.

class User < ActiveRecord::Base
   devise :omniauthable, :omniauth_providers => [:facebook]

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

Here we look for a user with that (provider: :facebook, uid: your_uid) pair, and create them if they aren’t in the database. For Facebook users, we create a random password. The expectation is that users logging in with Facebook don’t subsequently want to set a password.

Step 9 – Add a Controller to Handle the Callback

Now add a file:

app/controllers/users/omniauth_callbacks_controller.rb

Create a provider action, this action should have the same name as the provider. In this case, Facebook.

Now we have to write some code to handle the Omniauth callback.

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

We have to write a method in our ApplicationController:

def after_sign_in_path_for(resource)
    request.env['omniauth.origin'] || root_path
end

Your application is now ready.

Run rails s  open up your app and your sign up form should now have a “sign in with facebook” button.

Great, you did it! Now you have an application with email authentication as well as social network sign in.

 

Adrian Prieto

“If you are not willing to learn, no one can help you. If you are determined to learn, no one can stop you.” ― Zig Ziglar

Latest posts by Adrian Prieto (see all)

You may also like

4 Comments

  1. This was really helpful, but is there any significant different between Facebook and Twitter for the configuration? Thanks 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *