Facebook login in Rails using devise and omniauthable
みんなこんにちは!また嬉しいインターン生マフディーです!
I've learned so many new things this week and I can't wait to see what's next!
Lately, I've been working on Facebook integration in a Rails project so this time I'm going to show you how to setup Facebook login for users on your site!
In this case, we are going to use plataformatec/devise · GitHub for managing our users' authentication and various other things. Make sure to read the plataformatec/devise · GitHub page to understand how it works.
For the rest of this article, we are going to assume that we have a working devise installation with a model named 'User'.
First, start by adding the gem 'omniauth-facebook'
gem 'omniauth-facebook'
then running 'bundle install'!
Next, we have to add some columns to our database table 'users', so we run:
rails g migration AddColumnsToUsers provider uid name image rake db:migrate
Declare your Facebook app credentials in config/initializers/devise.rb as follow:
config.omniauth :facebook, "<FB_APP_ID>", "<FB_APP_SECRET>"
then enable 'omniauthable' in your model app/models/user.rb
devise :omniauthable, :omniauth_providers => [:facebook]
Now we need to implement a callback for when the user authenticates. We do this by replacing 'devise_for :users' in config/routes.rb with
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
then, creating the new controller at app/controllers/users/omniauth_callbacks_controller.rb which should have the following content:
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 end
and finally, add the following in your model models/users.rb
def self.from_omniauth(auth) new_user = false facebook_user = where(auth.slice(:provider, :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.image}?type=large" new_user = true end # Update already existing user unless new_user facebook_user.name = auth.info.name facebook_user.image = "#{auth.info.image}?type=large" facebook_user.save end facebook_user end
Done and done! You only have to include the Facebook login link now!
<%= link_to "Sign in with Facebook", user_omniauth_authorize_path(:facebook) %>
I have found plenty of resources explaining how to implement Facebook login, but most of them were unnecessarily confusing or outdated. This method should work without issues!