Rails Googleアカウントを利用したSNS認証


経緯

Googleアカウントを利用したSNS認証を実装したいと思い、記事を参考にしながら作業していたが、難航した為、補完した記事を書きたいと思いました。

前提

・devise機能は実装済とする。
・下記参考サイトをメインとし、不足及び不備の補完を行う。

参考サイト

https://qiita.com/akioneway94/items/35641ad30c2acb23b562

手順1 GoogleAPI登録

Googleplatformにログイン後以下の画像の通り操作


ナビゲーションメニューから「APIとサービス」を選択→「認証情報」をクリック→「同意画面を構成」をクリック


・必須項目(アプリ名、ユーザーサポートメール、メールアドレス)を入力して「保存して次へ」をクリック。

スコープ、テストユーザー、概要の画面は何もせず「保存して次へ」をクリック


・APIとサービスの認証情報をクリック→「認証情報を作成」をクリック→「OAuthクライアントID」をクリック

承認済みのリダイレクトURIを登録

・開発環境で使用したい場合
開発環境/users/auth/google_oauth2/callback
例:https://a072 ~ amazonaws.com/users/auth/google_oauth2/callback
・本番環境で使用したい場合
http://本番環境ドメイン/users/auth/google_oauth2/callback
※独自ドメインを取得しないと登録できません。

手順2 コードを記述

①devise.rbの編集

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']
:

②Gemfileの編集※解説あり

Gemfile.

 gem 'devise', git: "https://github.com/heartcombo/devise.git", branch: "ca-omniauth-2"
:
 gem 'dotenv-rails'
 gem 'omniauth', '1.9.1'
 gem 'omniauth-google-oauth2' 

その後、bundle install

アプリケーションのルートディレクトリ直下に.envを作成

③.envと.ignoreの編集

env.
GOOGLE_CLIENT_ID='クライアントID'
GOOGLE_CLIENT_SECRET='クライアントシークレット'

上記のクライアントID、クライアントシークレットをコピーして.envファイルに貼り付け

ignore.
.env

.ignoreファイルに.envを記述

④routes.rbの編集

routes.rb
Rails.application.routes.draw do
  :
  devise_for :users, controllers: {
    sessions: 'users/sessions',
    passwords: 'users/passwords',
    registrations: 'users/registrations',
    omniauth_callbacks: "users/omniauth_callbacks" #この行を追加
  }
  :

⑤データベースにカラムを追加

$ rails g migration AddOuthColumnToUsers provider:string uid:string

その後rails db:migrate

⑥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,
         # 以下を追加
         # google以外の認証をする場合は %i[twitter, facebook]
         :omniauthable, omniauth_providers: %i[google_oauth2]

  # クラスメソッドを作成します
  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
      # deviseのuserカラムに name を追加している場合は以下のコメントアウトも追記します
      # user.name = auth.info.name
      user.email = auth.info.email
      user.password = Devise.friendly_token[0,20]
    end
  end
end

⑦user/omniauth_callbacks_controller.rbの編集

user/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)
    # 先ほどuser.rbで記述したメソッド(from_omniauth)をここで使っています
    # 'request.env["omniauth.auth"]'この中にgoogoleアカウントから取得したメールアドレスや、名前と言ったデータが含まれています
    @user = User.from_omniauth(request.env["omniauth.auth"])
    sign_in_and_redirect @user, event: :authentication
    set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
  end

  def failure
    redirect_to root_path
  end
end

⑧app/views/devise/shared/_links.html.erbの修正

app/views/devise/shared/_links.html.erb
#変更前
 :
    <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %><br />
 :

#変更後    
 : 
  <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", user_google_oauth2_omniauth_authorize_path %><br />
 :

※Gemfileの解説

2021年1月22日現在、ominiauthnの最新バージョンに対して、deviseが対応できていない。よって、ominiauthのバージョン1.~をinstallし、deviseは指定のURL及びbranchにて実装する。

エビデンスサイト

https://rubygems.org/gems/omniauth/versions?locale=ja
https://github.com/heartcombo/devise/pulls

                             以上。