OmniAuth on Rails
How to simplify signing in to a Ruby on Rails application by using accounts people already have
There is a lot of information out there about adding a “Sign in with Facebook” button to various types of websites, but a lot of that information is confusing to follow.
This post provides a step-by-step guide to adding “Sign in with …” buttons for a recent Ruby on Rails application using Devise for user authentication. These sign in buttons use a technology called OmniAuth (OAuth for short).
If you are building a small application, you may want to help your users not having to remember an additional password by using only OmniAuth.
The code for the demo app is available on GitHub at https://github.com/monkbroc/omniauth-demo
Here’s the final result
Creating the application
Start a new Rails application
rails new omniauth_demo
Add OmniAuth and a couple providers to the Gemfile
# User account management
gem 'devise', '~> 3.4'
# To manage environment variables locally
Install the new gems
Create a User model that can only be authenticated with OmniAuth
rails generate devise:install
rails generate devise User
The User model
This is the User model.
Notice that the User model doesn’t have :database_authenticatable so the user won’t have a password inside this application.
The :developer OmniAuth provider is used to sign in during development. It simply asks for a name and email (no password) and logs in with that email. It is necessary because OmniAuth doesn’t work on a development machine, only on the production server because of the callback URLs (see below).
This is the migration to create the user
Run the migrations to create the users table
Signing up for OAuth credentials
You’ll need to have an “application” created on Facebook, LinkedIn, Twitter, Google and any other OmniAuth provider you want to use for your users to sign in.
Create an application on Facebook
Go to https://developers.facebook.com/apps and create a new Web app. You can skip the Quick Start.
Fill in Site URL and App Domains. You’ll also need to copy the App ID and App Secret for use later.
In the Advanced tab, make you need to add the callback URL to your application. It is your app site, followed by /users/auth/facebook/callback
You can also go to App Details to select a logo that will be displayed when a user signs in with Facebook toyour app.
Make sure to mark your app live in Settings when you are ready, otherwise only you (the app creator) will be able to sign in.
Create an application on LinkedIn
Go to https://www.linkedin.com/secure/developer and add a new application.
The important field to fill in is the OAuth 2.0 Redirect URLs. It is your app site, followed by /users/auth/linkedin/callback
You can also put a URL to a logo that will be shown to users signing in to your app with LinkedIn.
After you click Create application, make sure you grab the API Key and Secret Key.
Create an application on Twitter
Go to https://apps.twitter.com/ and create a new app.
Make sure you set the callback URL to your app site, followed by /users/auth/twitter/callback, and check “Allow this application to be used to Sign in with Twitter”
After creating the app, in the Settings tab you can add a logo.
In the Keys and Access Tokens tab, grab the API key and API secret.
Create an application on Google
Go to https://console.developers.google.com and click Create Project.
In the APIs section, enable the Google+ API and the Google Contacts API. Without this, signing in with Google will fail with the error “Could not authenticate you from GoogleOauth2 because Invalid credentials.”
From the Credentials section, click Create new Client ID and select Web application.
In the next steps, the important setting is again setting the callback URL to to your app site, followed by /users/auth/google_oauth2/callback (it has to be google_oauth2 because of the omniauth-google-oauth2 gem)
Copy the Client ID and Client Secret for later.
Adding OmniAuth API Keys and Secret to the Rails application
Finally we can add the keys we generated above to the Rails application.
For development, store the keys in the .env file at the root of the Rails application. Make sure the .env file is not checked in to git.
We add all the OmniAuth providers configured in the User model to the Devise initializer
Configuring routes and controllers
We need to add the OmniAuth controller to the Rails router. Also, since we don’t have :database_authenticatable in the User Devise configuration, we need to manually define the sign_in and sign_out routes.
The callback controller provides the endpoints that we used above while configuring Facebook, LinkedIn, Twitter and Google. It finds or creates a user based on the provider and signs them in.
All that is left is to add the sign in/sign out button to the application layout and to add the OmniAuth provider logos on the sign in page.
The important piece here is to have the link to omniauth_authorize_path for each of the providers.
Deploy to the cloud
To see this in action, you have to deploy to a public webserver.
An easy solution is to use Heroku.
Make sure the app is under version control
git add -A
git commit -m "Initial version"
Create a Heroku application
heroku apps:create omniauth-demo
Add the OmniAuth API Keys and Secrets to the Heroku application. Don’t forget this step.
heroku config:set FACEBOOK_API_KEY=XXXXXXXXXXXXXXXX FACEBOOK_API_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX LINKEDIN_API_KEY=XXXXXXXXXXXXXX LINKEDIN_API_SECRET=XXXXXXXXXXXXXXXX TWITTER_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXX TWITTER_API_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX GOOGLE_OAUTH2_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX GOOGLE_OAUTH2_API_SECRET=XXXXXXXXXXXXXXXXXXXXXXXX
git push heroku
heroku run rake db:migrate
Trying it out
If you got all the way down here, congratulations! Thanks for reading.
Go try it out yourself at https://omniauth-demo.herokuapp.com
Check out the demo app at https://github.com/monkbroc/omniauth-demo and add OmniAuth to your app today!
If you have problems making this work, reach out to me on Twitter @monkbroc
Julien Vanier, CTO of MuniRent