Facebook Oauth with Rails

By: Eunice Choi & Christopher Mark

When adding Facebook Login to our most recent project, Accountabuddy, we noticed there lacks a step-by-step and complete tutorial on using the OmniAuth gem. Here we show you how you can easily implement Facebook log in to your Rails app. (note to mention: we did not use Devise)

1. Setting Up your App on Facebook

First you will need to register your app through Facebook for Developers. If logged in, you will see the option to Add a New App under My Apps.

This will open a box to select the type of platform for your app. After selection, you should see the following page to type in your app name:

After you create your app id, you will be taken to a new page with a field to input your site URL. For now, enter http://localhost:3000/

You now have access to your dashboard where you can access your App ID and App Secret, along with other information.

2. Storing your Keys via Figaro

(Refer to Andrei Istratii’s article for reference)

Now that you have your secret IDs, you will want to store them in a private file somewhere in your Rails app. We went with the Figaro gem, which helps manage secret API keys while being Heroku-friendly.

Add a newline to your Gemfile:

gem ‘figaro’ 

Once added, run ‘bundle install’ in your command line:

$ bundle install

Also, run ‘figaro install’ in your command line:

$ figaro install

This creates an application.yml file in your config folder and will add it to the .gitignore file so that secrets aren’t uploaded in a public repo.

Now, open config/application.yml and type in:

FACEBOOK_APP_ID: "123123123"
FACEBOOK_APP_SECRET: "abcde1a2bcdef3abc4a56789abcdef"

In your config/secrets.yml, you should see something like this:

secret_key_base: a8d5a5706cf53...
facebook_app_id: <%= ENV[“FACEBOOK_APP_ID”] %>
facebook_app_secret: <%= ENV[“FACEBOOK_APP_SECRET”] %>
secret_key_base: 432cb5d950462...
facebook_app_id: <%= ENV[“FACEBOOK_APP_ID”] %>
facebook_app_secret: <%= ENV[“FACEBOOK_APP_SECRET”] %>
secret_key_base: <%= ENV[“SECRET_KEY_BASE”] %>
facebook_app_id: <%= ENV[“FACEBOOK_APP_ID”] %>
facebook_app_secret: <%= ENV[“FACEBOOK_APP_SECRET”] %>

Congrats! You have successfully hidden your keys.

3. Implementing OmniAuth Facebook Gem

There is one more gem that you will need to install.

Add ‘omniauth-facebook’ to your Gemfile:

gem ‘omniauth-facebook’

and bundle install in your command line :

$ bundle install

4. Updating the User Table

In order to apply Facebook OAuth for your users, you will need to update your user migration table.

In your command line, type in:

$ rails generate migration AddColumnsToUsers provider:string, uid:string

This will add provider and uid columns to the user table. The provider specifies the type of OAuth while the uid specifies the unique ID of the user. The new migration file should look like this:

class AddColumnsToUsers < ActiveRecord::Migration
def change
add_column :users, :provider, :string
add_column :users, :uid, :string

Now, migrate.

$ rake db:migrate

5. Configuring OmniAuth

When you installed the omniauth-facebook gem, it created the following file: config/initializers/omniauth.rb

Update the omniauth.rb, so that it looks like this:

OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, Rails.application.secrets.facebook_app_id,
Rails.application.secrets.facebook_app_secret, scope: ‘public_profile’, info_fields: ‘id,name,link’

You can edit the scope and info_fields depending on the level of access you have in your application. Explore https://developers.facebook.com/docs/facebook-login/permissions to view different permission options. Be aware that you might have to request permissions for certain levels.

6. Updating the User Model

You will now update the User model so that your app can save a new user to the database or login if that user already exists. The following method will check for this:

def self.create_with_omniauth(auth)

user = find_or_create_by(uid: auth[‘uid’], provider: auth[‘provider’])
user.email = “#{auth[‘uid’]}@#{auth[‘provider’]}.com”
user.password = auth[‘uid’]
user.name = auth[‘info’][‘name’]
  if User.exists?(user)

Let’s break down what is happening here.

user = find_or_create_by(uid: auth[‘uid’], provider:  auth[‘provider’])

The ActiveRecord method find_or_create_by will find the user if the user exists or create a new user if the user does not exist. Then it will set the user to a variable called user. You can update your user attributes to fit your User table. For now, we just save the email, password, and name.

if User.exists?(user)

The second half of the method is a simple control flow:

  • If the user exists, return user
  • Else, save new user in the database and return user

7. Configuring your routes.rb

Let’s update your routes.rb so that when a user signs in via Facebook, your application knows to direct to the session#create route.

Add the following get routes to your config/routes.rb

Rails.application.routes.draw do
get ‘auth/facebook/callback’, to: ‘sessions#create’
get ‘auth/failure’, to: redirect(‘/’)

8. Updating your Sessions Controller

One last thing!

You will need to add logic to your create route in your sessions controller. Now that you’ve implemented OAuth, you want your users to be able to login via Facebook as well as your application’s own login system.

We have created a simple create route for you. In your sessions controller, add the following:

def create
if request.env[‘omniauth.auth’]
user = User.create_with_omniauth(request.env[‘omniauth.auth’])
session[:user_id] = user.id
redirect_to user_path(user.id)
user = User.find_by_email(params[:email])
user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to user_path(user.id)

and… that’s it!

Yay! You have successfully implemented Facebook login to your Rails application. We hope you found this tutorial very useful. Please feel free to share your thoughts below!