Tutorial

How To Configure Devise and OmniAuth for Your Rails Application

Published on September 12, 2014
How To Configure Devise and OmniAuth for Your Rails Application

Introduction

Most Ruby on Rails applications require user registration and authentication mechanisms. Developing these from scratch requires a lot of time and effort – thankfully, there’s Devise. Using the Devise gem, you can set up a full-fledged user authentication system within minutes.

However, you could make your users happier by allowing them to access your application without creating a new account. They could simply log in using their existing Facebook, Twitter, Amazon, or DigitalOcean accounts. In fact, you could support authentication with any popular OAuth service provider. OAuth support is provided by the OmniAuth gem. In this tutorial, we shall create a simple application that uses both Devise and OmniAuth.

Prerequisites

Before you get started, make sure you have the latest versions of RVM, Ruby, and Rails installed on your host. If you don’t, please follow the instructions here: How To Install Ruby on Rails on Ubuntu 12.04 LTS with RVM

This tutorial has been tested with Ruby 2.1.2 and Rails 4.1.5.

Step 1 - Create a New Rails Application

It is recommended that you have all your Rails applications in a separate directory.

You should create one now.

mkdir rails_apps
cd rails_apps

You have to initialize the RVM environment before you start issuing Rails commands.

If you take a break while following this tutorial, remember to do this every time you restart your terminal session.

. ~/.rvm/scripts/rvm
rvm use ruby --default

Let us call the new application myapp. After creating the application, use cd to enter the application’s base directory.

rails new myapp
cd myapp

Note: All Rails commands should be run from inside your application’s directory, which in this case is ~/rails_apps/myapp.

Step 2 - Add the Required Gems to the Gemfile

We’ll need the Devise and OmniAuth gems. In addition, you will also need a separate gem for every OAuth service provider you wish to support. For this tutorial, we’ll support login using DigitalOcean, so we need the omniauth-digitalocean gem.

Add the following lines to the end of the file ~/rails_apps/myapp/Gemfile. You can use nano as your text editor.

gem 'therubyracer'
gem 'devise'
gem 'omniauth'
gem 'omniauth-digitalocean'

You will need similar gems to support other providers. For example, to support Facebook, you will need omniauth-facebook. Here are some such gems for your reference:

  • Twitter - omniauth-twitter
  • Amazon - omniauth-amazon
  • Google - omniauth-google
  • Github - omniauth-github

Install the newly added gems.

bundle install

Step 3 - Add Basic Functionality to the Application

Let us quickly add a few pages to this application for testing. Eventually these pages will be accessible only after logging in.

We can use Rails’ scaffolding feature for this. Using the rails g scaffold command, we simply specify the details about a model, and Rails generates fully functional pages to perform CRUD (Create Read Update Delete) operations on that model. In other words, all the associated controllers and views are generated, along with the model file.

rails g scaffold Product name:string price:integer description:text
rake db:migrate

Next, we have to define the root of this application.

Edit ~/rails_apps/myapp/config/routes.rb, and add the line root 'products#index' to specify the root of the app, just below the existing resources line. You can ignore all of the lines that are commented out. When you’re done, the active lines in the file will look like this:

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

Go ahead, test your application now. Start the development server by typing in:

rails s

Visit http://localhost:3000/ from your browser. If you’re developing remotely, please replace localhost with the appropriate IP address or domain for your Droplet. 3000 is the default port number for the development server.

For now, no login is required. Add a couple of products by clicking on “New Product”. Once you are satisfied that your application is working as expected, go back to the terminal and press Ctrl+C to stop the server.

Step 4 - Set Up Devise

Type the following commands to add Devise authentication support.

rails generate devise:install
rails generate devise User
rake db:migrate

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

Our app now has a basic authentication system, where users can register themselves, and then log in. However, all the pages are still directly accessible. To change this, edit ~/rails_apps/myapp/app/controllers/application_controller.rb and add authenticate_user! as an action that has to be performed before serving any page.

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

If you want to, you could start the development server again with the rails s command, and check out these newly added pages by visiting http://localhost:3000/ (again, use your own domain or IP address). You should see a page that looks like this:

Sign In page

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

Step 5 - Update the User Model to Support OmniAuth

If you started the server again, stop it with CTRL-C. Add a new column called uid to the model that Devise generated.

rails g migration AddColumnsToUsers provider uid
rake db:migrate

Step 6 - Get the Client ID and Client Secret from the OAuth Service Provider

Visit the service provider’s website and register your application there. All the service providers have different registration procedures. For DigitalOcean, refer to the tutorial here: How To Use OAuth Authentication with DigitalOcean as a User or Developer

You will be asked for a callback URL during the registration process. There is a separate callback URL for each provider. Here are the callback URLs for a few popular service providers:

  • Digital Ocean: http://localhost:3000/users/auth/digitalocean/callback
  • Facebook: http://localhost:3000/users/auth/facebook/callback
  • Amazon: http://localhost:3000/users/auth/amazon/callback
  • Twitter: http://localhost:3000/users/auth/twitter/callback
  • Google: http://localhost:3000/users/auth/google/callback

Please replace localhost with an IP address or domain that resolves to your Droplet. At the end of the registration process, you will be provided with your client ID and client secret. You will use these values in the next step.

Step 7 - Update the Devise Initializer

Edit ~/rails_apps/myapp/config/initializers/devise.rb to add the client IDs and secrets at the bottom of the file, just before the end line. It is also a good idea to update the mailer_sender to something that has your own server’s name and user. You don’t need to make any other changes beyond those two items.

After editing, your file would look like this (there will also be many commented lines in the file):

Devise.setup do |config|
  #Replace example.com with your own domain name
  config.mailer_sender = 'mailer@example.com'

  require 'devise/orm/active_record'
  config.case_insensitive_keys = [ :email ]
  config.strip_whitespace_keys = [ :email ]
  config.skip_session_storage = [:http_auth]
  config.stretches = Rails.env.test? ? 1 : 10
  config.reconfirmable = true
  config.expire_all_remember_me_on_sign_out = true
  config.password_length = 8..128
  config.reset_password_within = 6.hours
  config.sign_out_via = :delete

  #Add your ID and secret here
  #ID first, secret second
  config.omniauth :digitalocean, "db381dc9990be7e3bc42503d0", "5b0824c2722b65d29965f1a1df"
end

Step 8 - Update the User Model

The User model that Devise generated has to be changed to specify the service providers that we want to use. We’re adding three items to the existing list (:omniauthable, :omniauth_providers => [:digitalocean], and don’t forget the extra comma!). We also create a new method named from_omniauth to extract the information that is available after the authentication.

After editing it, your ~/rails_apps/myapp/app/models/user.rb should look like this:

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
	 :omniauthable, :omniauth_providers => [:digitalocean]

  def self.from_omniauth(auth)
	  where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
		user.provider = auth.provider
		user.uid = auth.uid
		user.email = auth.info.email
		user.password = Devise.friendly_token[0,20]
	  end
  end
end

Save the file.

Step 9 - Add a Controller to Handle the Callback URLs

First, edit ~/rails_apps/myapp/config/routes.rb and update the devise_for line to specify the name of the controller that will be handling the callbacks. Let us simply call it callbacks. Your file should now look like this (minus the commented sections):

Rails.application.routes.draw do
  devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
  resources :products
  root 'products#index'
end

Then, create a new file ~/rails_apps/myapp/app/controllers/callbacks_controller.rb.

Add the following code to it:

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

If you have used more OAuth providers, you will need a separate method for each of them. The name of the method should match the name of the provider. For example, to add support for Facebook, your method will be defined using def facebook.

Your application is now ready. Fire up your server again:

rails s

Visit your home page. Since we’re testing the login feature, you may want to do this in a session without stored data, such as a Chrome Incognito Window. You should see a Sign in with Digitalocean link. Click on it. You should be redirected to DigitalOcean’s login page. After a successful login, you will be redirected back to your own application, and the products page will be shown.

Sign in with DigitalOcean

Conclusion

You now have a modern user authentication system for your app, where users can sign in using an email address, a social networking account, or another popular service.

If you ever decide to take this app to production on a Droplet, you can refer to the tutorial here: How To Launch Your Ruby on Rails App with the DigitalOcean One Click Image. If you add your app to a new Droplet, don’t forget to go back to Step 6 to update your DigitalOcean API settings with your production server’s callback URLs.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Hathy A

author



Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
10 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

I followed these directions exactly and it is not working. I am authorizing digital ocean, then it redirects me back my application, but I am not signed in. It simply redirects me to the sign in page and does not add a user to my database.

Super helpful, thanks!

I am trying this on a production server that does not include :3000 in the URI. I am getting The redirect uri included is not valid. Iv’e tried it with and without the :3000 appended, but I am getting the same error.

thanks for your article ! devise is the best gem to create quickly user-based web-app and omniauth is very suitable for social network authentification :)

I use both of them in my ruby on rails online training

Hi, great article thanks. Due an update though?

This comment has been deleted

    no matter what you do you can’t change the redirect url

    The redirect URI in the request, http://localhost:8000/users/auth/google_oauth2/callback, does not match the ones authorized for the OAuth client. Visit

    I tried to implement the same tutorial for Facebook but i get error at Valid OAuth redirect URIs can any one help me

    Just want to thank you for such a great tutorial that was very easy to follow! Thank you!

    created an app that uses the steam Omniauth to authenticate users. I want to put it in my portfolio but the problem is that people without a Steam account won’t be able to see anything besides the index (login) page. I am trying to have it log in automatically using my user and password. What I saw so far was using omniauth-automatic gem but I’m not sure that’s the right way. help?

    Try DigitalOcean for free

    Click below to sign up and get $200 of credit to try our products over 60 days!

    Sign up

    Join the Tech Talk
    Success! Thank you! Please check your email for further details.

    Please complete your information!

    Get our biweekly newsletter

    Sign up for Infrastructure as a Newsletter.

    Hollie's Hub for Good

    Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

    Become a contributor

    Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

    Welcome to the developer cloud

    DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

    Learn more
    DigitalOcean Cloud Control Panel