【Rails】SNS認証 ~Google編~

#GoogleでのSNS認証 

この記事では、railsでgoogleでの認証を実装していきます！

##ゴール
**googleでサインインできるようになる！**
以下の画像ようにgoogleでログインできるよう実装していきます！
![スクリーンショット 2021-05-15 13.53.43 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820462/2adab651-6ab1-5513-be65-033164973a11.png)

#前提
ログイン機能 **devise** を導入していること
rootページが存在していること

#Google Cloud Platformの登録
Googleで認証できるように、まずは以下のサイトから設定をしましょう！
https://console.cloud.google.com

![スクリーンショット 2021-05-15 14.03.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820462/ee3a1fd5-bfde-4aba-d190-21e28e9663a9.png)
![スクリーンショット 2021-05-15 14.03.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820462/e841092c-d65f-2619-e0e0-645371940d0b.png)
![スクリーンショット 2021-05-15 14.03.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820462/a7efc011-bbcb-9f00-e1df-84d628dbb4fc.png)
![スクリーンショット 2021-05-15 14.03.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820462/f245619b-5c58-969e-350c-c3884eab1dff.png)
![スクリーンショット 2021-05-15 14.04.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820462/84aac8e1-f0dc-2e69-8aef-f665e4f469e6.png)
![スクリーンショット 2021-05-15 14.05.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820462/cf97996a-873b-62a9-3f5d-40b609593fec.png)
![スクリーンショット 2021-05-15 14.05.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820462/be587593-ffae-e14a-3b4a-418ff699b2b7.png)
![スクリーンショット 2021-05-15 14.05.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820462/f8d4ded5-1c0b-ab39-bcf6-4ae4700cb476.png)

URLは開発環境の場合、こちらを入力してください
`http://localhost:3000/users/auth/google_oauth2/callback`
本番環境でも使われる場合は、こちらを入力してください
`http://本番環境URL/users/auth/google_oauth2/callback`

#実装
まず、deviseの設定ファイルを変更します。
config/initializers/devise.rbを開いて、その270行目付近をみてください。

```ruby:config/initializers/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を追加していきます。

以下gemの説明
**dotenv-rails：**環境変数の管理用のgem
**omniauth-google-oauth2：**GoogleのAPIを利用して認証を行うgem
**omniauth-rails_csrf_protection：**"OmniAuth" の脆弱性対策を行うgem

```ruby:gemfile
gem 'dotenv-rails'
gem 'omniauth-google-oauth2'
gem 'omniauth-rails_csrf_protection'
```

`bundle install`します。

アプリケーションのルートディレクトリ直下に`.env`を作成します。
![スクリーンショット 2021-05-15 13.37.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820462/536bd589-b457-67f4-0e1f-c8d8f9bfa1a3.png)

ここで「=」の後のそれぞれの値は先ほどの認証情報で取得したキーに書き換えておいてください（自分が取得したキーは絶対他言しないように！！また数字は個々人によって変わります）。

```ruby:.env
GOOGLE_CLIENT_ID='クライアントIDを入力'
GOOGLE_CLIENT_SECRET='クライアント シークレット'
```
以下の`クライアントID`,`クライアントシークレット`をコピーして上に貼り付けてください！
![スクリーンショット 2021-05-15 14.22.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/820462/3b51b168-e898-7913-633d-c672edd03bca.png)
　最後に隠しておきたいデータを定義した.envファイルをみんなに公開してしまっては意味が無いのでこのファイルは公開しないようにします。アプリケーションディレクトリにある`.gitignore`に下記を追加します。
<font color="red">**※もし`.gitignore`ファイルがない場合はアプリケーションディレクトリーにて作りましょう！**</font>

```ruby:.gitignore
#省略
# 以下を追記
.env
```

#ルーティングの編集
```ruby:config/routes.rb
Rails.application.routes.draw do
  # deviseのコントローラを編集するときは以下を記述しないと変更が反映されないので注意

  # 変更前
  devise_for :users
　# ここまで

  # 変更後
  devise_for :users, controllers: {
    # deviseの階層を編集した場合は適宜pathを編集してください
    omniauth_callbacks: "users/omniauth_callbacks"
  }
　# ここまで

  resources :posts

  root 'posts#index'
end

```

# userモデルを編集
`user.rb`に処理を書いていきます。
ここでの注意点は２点あります！
1. <font color="red"> :validatableの後ろに,「カンマ」を入れることです！</font>（,を入れないとエラーが出てしまいます。）
2. deviseのuserカラムに name を追加している場合は以下のコメントアウトは外します！
     ` # user.name = auth.info.name`


```ruby: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
```

DBに`where`で検索したオブジェクトが存在しなければ、何も処理を行わず、
DBに`where`で検索したオブジェクトが存在していれば、`user`オブジェクトに`do`以降の処理を入力してDBに保存する処理になってます。

# データベースにカラムを追加する
認証に必要なカラム`provider`カラムと、`uid`カラムを作成するためのマイグレーションファイルを作成します

```terminal
$ rails g migration AddOuthColumnToUsers provider:string uid:string
```

`rails db:migrate`

#omniauthの処理を編集します

準備としてcontrollersファイルの配下に**usersフォルダ**を作成しましょう！
そしてそのフォルダの中に**omniauth_callbacks_controller.rb**を作成します！

```ruby:controllers/users/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

```

#buttonの作成
最後に、sign inページのボタンを実装していきます！

```ruby:views/users/shared/_links.html.erb
 #変更前
  <%- if devise_mapping.omniauthable? %>
    <%- resource_class.omniauth_providers.each do |provider| %>
      <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), method: :post %><br />
    <% end %>
  <% end %>
 #ここまで

 #変更後
  <%- if devise_mapping.omniauthable? %>
　　　<%= button_to 'Sign in with Google', user_google_oauth2_omniauth_authorize_path %>
  <% end %>
 #ここまで
```
`user_google_oauth2_omniauth_authorize_path`は是非`rails routes`で確認して見てください！

以上でGoogle認証の実装は完了となります！
今回は非常に様々な方の記事を引用させていただきました。ありがとうございます。
参考記事：https://qiita.com/akioneway94/items/35641ad30c2acb23b562

エラーや不手際がありましたら是非連絡ください。