[Ruby] SNS authentication using Rails google

2 minute read

Goal

Click the googole authentication link image.png

Select account image.png

Successful authentication!! image.png

Create base

  • Introduce devise
  • Create posting function with scaffold ![ezgif.com-video-to-gif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/a17fb807-23c2-03ee-(d339-02d61b26acaa.gif)

I have created an application that allows me to log in and create posts.

Set #google image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png For the development environment, enter this URL http://localhost:3000/users/auth/google_oauth2/callback Please enter here if it is also used in the production environment. http://production environment URL/users/auth/google_oauth2/callback

I will edit the code

Set environment variables.

devise.rb


# ==> OmniAuth
# Add a new OmniAuth provider.Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github,'APP_ID','APP_SECRET', scope:'user,public_repo'
config.omniauth :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET']

I used dotenv-rails to manage environment variables.

gemfile


gem'dotenv-rails'

Do a bundle install. Create .env directly under the root directory of the application

Copy the following Client ID and Client Secret

image.png

Paste in .env as follows

.env


GOOGLE_CLIENT_ID='Enter Client ID'
GOOGLE_CLIENT_SECRET='Client Secret'

As for the environment variable, I think it is better to add .env to .ignore when pushing to github.

.ignore


# Add the following
.env

gemfile edit

gemfile


gem'omniauth-google-oauth2'

Add the above gem

bundle install

Routing edit

gemfile


Rails.application.routes.draw do
  When editing the controller of # devise, be careful because the change is not reflected unless the following is written.
  devise_for :users, controllers: {
    If you edit the #devise hierarchy, edit the path accordingly
    omniauth_callbacks: "users/omniauth_callbacks"
  }

  resources :posts

  root'posts#index'
end

Add columns to the database

Create a migration file to create the columns required for authentication, the provider column and the uid column

$ rails g migration AddOuthColumnToUsers provider:string uid:string

rails db:migrate

edit user model

I will write the process in user.rb

user.rb



class User <ApplicationRecord
  # Include default devise modules.Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
     # Add below
     # If you authenticate other than google, it will be %i[twitter, facebook] etc.
         :omniauthable, omniauth_providers: %i[google_oauth2]

  # Create class method
  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
      If you have added name to the user column of # devise, add the following comment out
  # user.name = auth.info.name
      user.email = auth.info.email
      user.password = Devise.friendly_token[0,20]
    end
  end
end

The first method used here is first_or_create. It’s quite convenient…

If the object searched by where does not exist in the DB, do nothing, If the object searched by where exists in DB, the process after do is input to user object and saved in DB.

Should I try various things with rails console -s once! If you use rails console -s, you can rest assured that no changes will be made to the database.

Edit the processing of #omniauth

omniauth_callbacks_controller.rb


# frozen_string_literal: true

class Users::OmniauthCallbacksController <Devise::OmniauthCallbacksController
  # callback for google
  def google_oauth2
    callback_for(:google)
  end

  def callback_for(provider)
# I'm using the method (from_omniauth) I wrote in user.rb earlier
#'request.env["omniauth.auth"]' This contains the email address obtained from the googole account and the data such as name.
    @user = User.from_omniauth(request.env["omniauth.auth"])
    sign_in_and_redirect @user, event: :authenticationset_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
   end

   def failure
     redirect_to root_path
   end
end

I think you can do sns authentication with google! !!

Reference

[Implement user registration on Facebook/Twitter/Google with Devise & Omniauth] (https://qiita.com/kazuooooo/items/47e7d426cbb33355590e)