Login via Facebook in Rails App

Login via Facebook in Rails App

Facebook authorization with devise and omniauth in production (Heroku)

Who isn’t tired of creating an account on every possible website? Isn’t it just better to click and login using your account from one of Internet giants(like Facebook)? It’s convenient for users and fairly simple to set up. I know you’re in a hurry, so let’s begin!

Before we get into hacking, some things need to be set up:

  1. Precious Gems!
  2. A Facebook App and credentials
  3. Credentials set up in production (I’ll be using Heroku)
  4. Evil plan for taking over the world*

*Crucial

 

Setting it up

  1. Gems we will need:

gem 'devise'
gem 'omniauth-facebook


Yep, that’s all!

  1. Creating FB app and getting the creds:

  • Login to your Facebook account.
  • Go to https://developers.facebook.com/apps/
  • Click on ‘ + Add a New App ‘ button.
  • Pick the name and contact mail for your app.
  • Click on ‘Create App Id’
  • From Dashboard, take App Id and App Secret. No, don’t run, they are yours!
  • You can let your evil chuckle out (you are permitted to make an evil laugh only after we are finished).
  1. Now, go to the Heroku site and create a new app. Or use your existing one, whatever, I don’t care. Just do your job, ok?

      In Heroku, click on the app and go to the Settings tab, like in the screenshot below:

 

      Now, click on the ‘Reveal Config Vars’ button. You guessed it, config variables will be revealed to you. Like secret codes to the base of some lame superhero, you will someday destroy!

      Now just add the credentials. And name them good!

    For the last thing to do in the setting up section, copy or remember the name of your Heroku app.

    Then, head to the Facebook App from the section before and go to the Settings tab. On the bottom of the screen, you should have ‘ + Add platform ‘ button. Click on it, but please, be gentle.

    Choose ‘Website’ as the platform.

    Now you can add URL to your app, like this:

    You can Save Changes now. We are done setting up!

 

Finally: Coding!

We can start meddling with our application now. Feel free to bang on your keyboard as loud as you can!

Firstly, if you haven’t done it yet, make use of the devise gem:

rails generate devise:install
rails generate devise User

And add some fields to the created user, migrate after it:

rails generate migration AddColumnsToUser token uid name avatar
rails db:migrate

(We don’t need to specify type of the column – string is default one)

Now, head over to the config/initializers/devise.rb. You don’t have to scroll all the way down, but there is a OmniAuth section in the file. Paste this, and remember to change the link to your application in the last argument:

# config/initializers/devise.rb
config.omniauth :facebook,
  ENV['FACEBOOK_APP_ID'],
  ENV['FACEBOOK_APP_SECRET'],
  callback_url:  "https://yourevilapp.herokuapp.com/users/auth/facebook/callback"

After that, let devise know that the user is ‘omniauthable’ – in the user.rb:

 devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable,
     :omniauthable, :omniauth_providers => [:facebook]

And add new methods to handle new session and data:

def self.new_with_session(params, session)
  super.tap do |user|
    if data = session["devise.facebook_data"] &&  session["devise.facebook_data"]["extra"]["raw_info"]
      user.email = data["email"] if user.email.blank?
    end
  end
end

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

We are nearly done! Isn’t it awesome? One last thing. Let’s take control of our controllers and add the new file in the new directory:

# yourevilapp/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
      set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

  def failure
    redirect_to root_path
  end
end

Customize routes to call this controller:

devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }

And we are good to go! Push the changes to Heroku and check out your sweet sweet new Facebook authorization!

And, if you have done everything right, you can finally let your dramatic and evil laugh out!  

Good job!

Post a comment