gem omniauth-google-oauth2とgem deviseを使ったグーグルログイン認証の実装


gem deviseを使ったグーグル認証によるログイン実装

簡易的にログイン機能を実装してみます。

環境構築

新ディレクトリ作成

ディレクトリに移動して
$ bundle init

gem 'rails'

$ bundle install

$ bundle exec rails db:create

$ rbenv global 2.6.3

$ rbenv rehash

$ rails new . --skip-test

実装前準備

①gcp(google cloud platform)設定

  • グーグルアカウントでログイン

こんな画面が現われます。

  • OAuth同意画面

→アプリケーション名、承認済みドメイン入力

→承認済みドメインは外部からのアクセスを可能にするために 後ほどngrokでドメインを設定します
(ngrokのサーバー接続画面のforwarding部分のドメインです)

  • 認証情報を作成

→承認済みの JavaScript 生成元 URI
localhost:3000

→承認済みのリダイレクト URI
http://localhost:3000/users/auth/google_oauth2/callback

②ngrok設定

  • ngrokページから、signup(新規登録)

・ダウンロードngrok
→ZIPファイルダウンロード

・解凍してインストール
→ngrok.zipをダブルクリック

・アカウントを接続する

$cd ~/Downloads/

でダウンロードディレクトリへ移動


$ ./ngrok authtoken ********

  • サーバへ → $ ./ngrok http 3000

成功画面

実装

$ rails g controller static_pages home
routes.rb
Rails.application.routes.draw do
  root to: "static_pages#home"
  get 'static_pages/home'
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
  • gem 'devise' をインストール

  • $ rails g devise:install

  • $ rails g devise user

  • フラッシュメッセ追加
    app/views/layouts/application.html.erb.に

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

を追加

  • トップページ
<h1>StaticPages#home</h1>
<% if user_signed_in? %>
  <%= link_to "Sign out", destroy_user_session_path, method: :delete %>
<% else %>
  <%= link_to "Sign in", new_user_session_path %>
<% end %>  

application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>TwitterAuthExample</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <p class="notice"><%= notice %></p>
    <p class="alert"><%= alert %></p>
    <%= yield %>
  </body>
</html>
  • 認証情報

URI
http://localhost:3000

承認済みのリダイレクト URI
http://localhost:3000/users/auth/google_oauth2/callback

  • credentialsにキーなどの情報を記載

$ EDITOR="vim" rails credentials:edit

google_oauth2:
  client_id: xxxxx
  client_secret: xxxxx

コンソールで

Rails.application.credentials

を実行して確認

gem 'omniauth-google-oauth2'
をインストール

config/initializer/devise.rb
以下を追加

config/initializer/devise.rb
config.omniauth :google_oauth2, Rails.application.credentials.google_oauth2[:client_id], Rails.application.credentials.google_oauth2[:client_secret], scope: 'email', redirect_url: "#{ENV['HOST']}/users/auth/google_oauth2/callback"
user.rb
class User < ApplicationRecord

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :omniauthable, omniauth_providers: [:google_oauth2]

  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
$ rails g migration add_oauth_columns_to_users

マイグレーションファイルの中身

class AddOauthColumnsToUsers < ActiveRecord::Migration[6.0]

  def change
    add_column :users, :provider, :string
    add_column :users, :uid, :string
  end
end

Rails.application.routes.draw do
  devise_for :users, controllers: {
      omniauth_callbacks: 'users/omniauth_callbacks'
  }
  root to: "static_pages#home"
  devise_scope :user do
    get '/users/sign_out' => 'devise/sessions#destroy'
  end
  get 'static_pages/home'

end

$ rails g devise:controllers users -c=omniauth_callbacks

omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def google_oauth2
    @user = User.from_omniauth(request.env['omniauth.auth'])


if @user.persisted?
      flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google'

 sign_in_and_redirect @user, event: :authentication
    else

  session['devise.google_data'] = request.env['omniauth.auth'].except(:extra) # Removing extra as it can overflow some session stores
      redirect_to new_user_registration_url, alert: @user.errors.full_messages.join("\n")
    end
  end
end

完成