Facebook OAuth with Rails

By: Eunice Choi & Christopher Mark

When adding Facebook Login to our most recent project, Accountabuddy, we noticed that there lacks a step-by-step and complete tutorial on using the OmniAuth gem. Here we show you how you can implement Facebook login 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 the 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 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 the 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:

development:
secret_key_base: a8d5a5706cf53...
facebook_app_id: <%= ENV[“FACEBOOK_APP_ID”] %>
facebook_app_secret: <%= ENV[“FACEBOOK_APP_SECRET”] %>
test:
secret_key_base: 432cb5d950462...
facebook_app_id: <%= ENV[“FACEBOOK_APP_ID”] %>
facebook_app_secret: <%= ENV[“FACEBOOK_APP_SECRET”] %>
production:
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 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
end
end

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

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 = User.where(
uid: auth[‘uid’],
provider: auth[‘provider’]
).first_or_create(
email: “#{auth[‘uid’]}@#{auth[‘provider’]}.com”,
password: auth[‘uid’],
name: auth['info']['name']
)
 if user.persisted?
user
else
user.save!
user
end
end

Let’s break down what is happening here.

user = User.where(uid: auth[‘uid’], provider: auth[‘provider’])

The ActiveRecord method where will search for a user with the uid and provider. The method first_or_create will set the existing user to a variable called user or create a new user if the user does not exist. (Credits to Dylan Drop for this suggestion). You can update your user attributes to fit your User table. For now, we just save the email, password, and name.

if user.persisted?
user
else
user.save!
user
end

The second half of the method is a simple control flow

  • If the user persisted, 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(‘/’)
end

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 Facebook 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 edit_user_path(user.id)
else
user = User.find_by_email(params[:email])
user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to user_path(user.id)
end
end

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!

Like what you read? Give Christopher Mark a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.