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

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

##前提
・devise機能は実装済とする。
・下記参考サイトをメインとし、不足及び不備の補完を行う。
#####参考サイト
・https://qiita.com/akioneway94/items/35641ad30c2acb23b562

##手順1　GoogleAPI登録
Googleplatformにログイン後以下の画像の通り操作

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031232/ef0e2d14-ffc1-3b4a-fcd6-b95fda5a05da.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031232/97df37c9-bb3b-c9d7-420b-2434fe2f34bc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031232/08147693-899a-116a-0502-44b7a6d3cb8b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031232/c62c8206-d2b4-bd4f-055b-4d491d402846.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031232/040017fe-a22b-c51a-1b3c-143b92eca421.png)
ナビゲーションメニューから**「APIとサービス」**を選択→**「認証情報」**をクリック→**「同意画面を構成」**をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031232/e3a2efe2-5fe1-1599-28b4-6aaf04fcd3d8.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031232/745b1f7f-2932-977c-ea9c-a0070cb188db.png)
・必須項目（アプリ名、ユーザーサポートメール、メールアドレス）を入力して**「保存して次へ」**をクリック。

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031232/e1720a7e-ed38-0fad-dee5-cdcb2ae65667.png)
・APIとサービスの認証情報をクリック→**「認証情報を作成」**をクリック→**「OAuthクライアントID」**をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031232/86ab9903-1f2c-d755-eca4-58e44979d05d.png)

###承認済みのリダイレクトURIを登録
・開発環境で使用したい場合
**開発環境/users/auth/google_oauth2/callback**
 例:<font color = "Red">https://a072　~　amazonaws.com/users/auth/google_oauth2/callback</font>
・本番環境で使用したい場合
**http://本番環境ドメイン/users/auth/google_oauth2/callback**
<font color = "Red">※独自ドメインを取得しないと登録できません。</font>


##手順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の編集<font color="Red">※解説あり</font>

```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の編集
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031232/c54955b8-96f6-5a55-589b-96e3f2b0bd81.png)

```.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 />
 :
```

###<font color="Red">※Gemfileの解説</font>
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

　　　　　　　　　　　　　　　　　　　　　　　　　　　　　以上。