Implementing Facebook authentication with Devise for your Rails 6 app
Tags: rails, ruby, howto, beginners
Published: 2020-08-21 19:19:55

---
title: Implementing Facebook authentication with Devise for your Rails 6 app
published: true
description: 
tags: #rails #ruby #howto #beginners
//cover_image: https://direct_url_to_image.jpg
---

Hello everyone,

This week, I will be writing about how to setup Facebook authentication for your Rails app.

## Prerequisites
* An app using Rails 6 with devise setup for authentication
* A working knowledge of creating a new Rails app
* A working knowledge of devise for authentication
* An active Facebook account

## Facebook Authentication
To implement Facebook auth, we need to create an app on Facebook that will generate an `APP_ID` and `APP_SECRET` for setting up devise omniauth later.

### Create Facebook app
* Go to [https://developers.facebook.com/](https://developers.facebook.com/)
* Click on `My Apps` in the navbar
* Click on `Add a new App`
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/upa08qfciq91fjdjbg2o.png)
* On the modal that pops up, select the `For Everything Else` option.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/dovb5pffiztapu9gqtld.png)
* Next, add your `App Display Name` and click the `Create App Id` button
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1f9jpr9ggfgbrktw05o7.png)
* Complete the security check and this should redirect you to the app
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/tlwqfft1toq5kn8pync7.png)
* On the sidebar, click on `Setting` and then click on `Basic`. You should be able to see your `APP_ID` and `APP_SECRET`. Copy and save for later.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/oqeivvsbfeai2bkvnzkf.png)
* In the `App domains`, add `localhost`. You can also add your add icon if you have one. 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/g05acajntgk7mwcrydp6.png)
* Scroll down to the end of the page and click on the `Add Platform`
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/05vtgp88ocvwk71dasgo.png)
* On the modal that pops up, select `Website`
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/qse6zk4t78hi6tum1swm.png)
* Add `http://localhost`
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/xemzkxc9yabjzfwlhrow.png)
* Save your changes

### Setup Facebook Auth in devise
In this section, we will be setting up facebook auth in our rails app.
* Add the omniauth-facebook gem to your gemfile
```ruby
gem 'omniauth-facebook'
```
* Run `bundle install`
* Next we create a migration to add provider and uid to the user model. This stores the provider the user uses to register whether its `facebook` or `google`. 

```
$ rails g migration AddOmniauthToUsers provider:string uid:string
```
* Run `rake db:migrate`
* Next, we need to update the devise initializer file to include the `APP_ID` and `APP_SECRET` we saved for later
```ruby
# config/initializers/devise.rb
config.omniauth :facebook, "APP_ID", "APP_SECRET"
```

Note: If you chose to use the credentials to save your environment variables. You can use this command to edit it in your code editor. Run this code in your terminal. Change `code` part to your code editor if you don't use vscode.

```
$ `EDITOR="code --wait" bin/rails credentials:edit`
```

In the decrypted credential file, add the app_id and app_secret
```ruby
facebook:
  APP_ID: '<facebook_app_id>'
  APP_SECRET: '<facebook_app_secret>'
```
So your initializer file update will be 
```
config.omniauth :facebook, Rails.application.credentials.facebook[:APP_ID], Rails.application.credentials.facebook[:APP_SECRET], token_params: { parse: :json }
```
* Next we need to make the user model omniauthable. Add this to the user model 
```ruby
# app/models/user.rb
devise :omniauthable, omniauth_providers: %i[facebook]
```
* Next, we create an omniauth controller in a user folder to respond to facebook authentication.
```ruby
# app/controllers/users/omniauth_callbacks_controller.rb

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

    if @user.persisted?
      sign_in_and_redirect @user, event: :authentication #this will throw if @user is not activated
      set_flash_message(:notice, :success, kind: "Facebook") if is_navigational_format?
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"].except(:extra) # Removing extra as it can overflow some session stores
      redirect_to new_user_registration_url
    end
  end

  def failure
    redirect_to root_path
  end
end
```
* Next, we go back to the `user` model to add the `from_omniauth` self method. This method finds or creates a new user when they register. The name_split part of for those that store the first_name and last_name of their users.
```ruby
# app/models/user.rb
def self.from_omniauth(auth)
  name_split = auth.info.name.split(" ")
  user = User.where(email: auth.info.email).first
  user ||= User.create!(provider: auth.provider, uid: auth.uid, last_name: name_split[0], first_name: name_split[1], email: auth.info.email, password: Devise.friendly_token[0, 20])
    user
end
```
* Next, we update the routes file for include the new controller we just added
```ruby
# config/routes.rb
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
```
* Finally, we add the facebook button to our view using a facebook path provided by devise. You can use this same path for both registration and login. You just need to update the button description.

```erb
<%= link_to "Register with Facebook", user_facebook_omniauth_authorize_path %>
```

And that should add facebook auth to your app.

## Other Authentication
The process is quite similar for google authentication. We need to create a project for the app and then create the credentials for auth. I am going to attach a link to create credentials for google auth and the omniauth-google gem. 

[Create credentials on google](https://developers.google.com/adwords/api/docs/guides/authentication#webapp)
[Omniauth Google gem](https://github.com/zquestz/omniauth-google-oauth2)
[Omniauth twitter gem](https://github.com/arunagw/omniauth-twitter)
[Twitter guide for creating an app](https://developer.twitter.com/en/docs/apps/overview)

Let me know what you think and what to write about in the comment section.

Until next week