[Rails] Google, Twitter, Facebook authentication using Devise and Omniauth

Here's how to use Devise and Omniauth to implement social login functionality in your Rails app. For example, if you only want to use Google login, ignore the description for Twitter and Facebook.

Install Devise

Gemfile


gem 'devise'
$ bundle install
$ rails g devise:install

config/environments/development.rb


config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

erb:app/views/layouts/application.html.erb


<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>

Create Model

$ rails g devise User
$ rails db:migrate

config/routes.rb


Rails.application.routes.draw do
  devise_for :users #Will be added automatically
end

Create View

$ rails g devise:views users

Make it inaccessible without logging in

app/controllers/application_controller.rb


class ApplicationController < ActionController::Base
  before_action :authenticate_user!
end

If you can do this, restart the server. If you access other than the login page or new registration page, you will be skipped to the login screen, Access/users/sign_up and confirm that you can register as a user.

Set environment variables

Gemfile


gem 'dotenv-rails'
$ bundle install
$ touch .env

.env


HOST='hogehoge.com'
TWITTER_API_KEY=
TWITTER_API_SECRET=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
FACEBOOK_KEY=
FACEBOOK_SECRET=

I will get the ID and SECRET later, so it's OK now.

Install omniauth gem

Gemfile


gem 'omniauth-facebook'
gem 'omniauth-twitter'
gem 'omniauth-google-oauth2'
$ bundle install

Added column for omniauth to User table

$ rails g migration AddOmniauthToUsers provider:string uid:string
$ rails db:migrate

Edit initializer

config/initializers/devise.rb


config.omniauth :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], scope: 'email', info_fields: 'email', callback_url: "#{ENV['HOST']}/users/auth/facebook/callback"
config.omniauth :twitter, ENV['TWITTER_API_KEY'], ENV['TWITTER_API_SECRET'], scope: 'email', oauth_callback: "#{ENV['HOST']}/users/auth/twitter/callback"
config.omniauth :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'], scope: 'email', redirect_uri: "#{ENV['HOST']}/users/auth/google_oauth2/callback"
OmniAuth.config.logger = Rails.logger if Rails.env.development?

Create OmniauthCallbacksController

$ mkdir app/controllers/users/
$ touch app/controllers/users/omniauth_callbacks_controller.rb

controllers/users/omniauth_callbacks_controller.rb


class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    callback_for(:facebook)
  end

  def twitter
    callback_for(:twitter)
  end

  def google_oauth2
    callback_for(:google)
  end

  # common callback method
  def callback_for(provider)
    @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: "#{provider}".capitalize) if is_navigational_format?
    else
      session["devise.#{provider}_data"] = request.env["omniauth.auth"].except("extra")
      redirect_to new_user_registration_url
    end
  end

  def failure
    redirect_to root_path
  end
end

Edit User model

app/models/user.rb


class User < ApplicationRecord
  #To the default settings:omniauthable Added below
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :omniauthable, omniauth_providers: %i[facebook twitter google_oauth2]
  #Method called during omniauth callback
  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]
    end
  end
end

Edit routing

config/routes.rb


Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
  #abridgement
end

Check login screen and sign-up screen

Make sure that the link for social login has been added.  2020-12-25 12.27.45.png  2020-12-25 12.27.51.png

Settings for each platform

Twitter Get the API key and API key secret from Twitter Developers and set them in .env, referring to the following articles. https://dev.classmethod.jp/articles/twitter-api-approved-way/

.env


TWITTER_API_KEY='hogetwkeyhoge'
TWITTER_API_SECRET='fugatwsecretfuga'

Then play with Edit authentication settings and set the app domain/users/auth/twitter/callback to complete.  2020-12-30 18.21.57.png

Google While looking at the articles around here, create an app with GCP, get the client ID and client secret, and set it in .env https://qiita.com/nakanishi03/items/2dfe8b8431a044a01bc6#google

.env


OOGLE_CLIENT_ID='hogehogehoge.apps.googleusercontent.com'
GOOGLE_CLIENT_SECRET='dgpV8aMmmDzfugafuga'

Set domain/users/auth/google_oauth2/callback to approved redirect URI.  2020-12-30 18.38.52.png

Facebook Get AppID and AppSecret and set them in environment variables.

.env


FACEBOOK_KEY='foobarsdsfe'
FACEBOOK_SECRET='bazdejnerf'

Set domain/users/auth/google_oauth2/callback to Valid OAuth Redirect URIs.

reference

-[Rails] Implement user registration on Facebook/Twitter/Google at explosive speed using Devise & Omniauth --Qiita -Rails for Facebook and Google OAuth integration. SNS authentication method --Qiita

Recommended Posts

[Rails] Google, Twitter, Facebook authentication using Devise and Omniauth
SNS authentication using Rails google
[Rails] Implementation of SNS authentication (Twitter, Facebook, Google) function
Rails6 OmniAuth twitter Authentication Email conditional branch
Memorandum [Rails] User authentication Devise
Password hashing and authentication using JBcrypt
[Rails 6] Implementation of new registration function by SNS authentication (Facebook, Google)
[Rails 6] Register and log in with Devise + SNS authentication (multiple links allowed)
Implementation of user authentication function using devise (2)
July 2020 google login authentication with gem Omniauth
Creating a user authentication function using devise
Implementation of user authentication function using devise (3)
Run Docker environment Rails MySQL on Heroku. devise and hiding the twitter API
[Rails] devise
(Basic authentication) environment variables in rails and Docker
[Nuxt / Rails] POST implementation using axios and devise_token_auth