Rails　Googleログインを実装する　[SNS認証]　

# はじめに
SNS認証の記事って結構ある割に、gemのバージョンが非対応だったり、APIの登録だったりで躓く所が多くて色々ハマるところが多かったので、無事動くように色々試しながら書いてみました。

初学者の僕が書いたので、初学者でも基本的にはコピペで実装できるようには書いてるつもりです。（説明はよく読んでください！）
# ゴール　

>gooleアカウントでアカウント登録、ログインできるようになる。

# 前提
>gem 'devise' 導入済み

```:コマンドプロンプト
$ rails generate devise:install          # deviseの設定ファイル作成
$ rails generate devise user             # Userモデル(usersテーブル作成)
$ rails generate devise:views users      # usersのviewファイル作成

 ```  
具体的にはここら辺はやってる前提で

# STEP1  Google Cloud Platformに登録

>[ここからアカウント登録してください！](https://console.cloud.google.com)

## 登録が終わったら以下の手順で設定
**以下写真です。見にくくて申し訳ないです。**
![1個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/64db3d8b-74a5-ab0e-fcde-c047b7a01926.png)
![２個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/28182a34-9eb9-fb1b-11b2-f96a0d06b374.png)

![３個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/462f7978-6720-6de0-d095-795154e70bdc.png)
![４個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/0a046a93-ed19-769c-75f3-75107063f24f.png)
![5個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/cd4cddfb-d4e5-d721-1ad9-fcbafea184ef.png)
![6個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/629a9892-cc2c-0bfa-baef-d76651f80923.png)
![７個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/364c0142-19cc-2415-c1a9-f7944938ed2c.png)
![８個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/7ea3f871-9287-8038-afa0-045a4935ae00.png)
![９個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/52f4ca12-4d90-16a5-9cdf-c8aa76db9640.png)
#### <font color="Red">↑↑↑入力必須欄以外は何もいじらずに進んでください！</font>
## 次に認証情報を作成します（よく読んでね）
![10個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/78d1c4a7-e340-d5a4-156a-15c7a27f6241.png)


![11個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/f6c30184-9900-d21a-8643-0bbe9e4db6f3.png)
![12個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/4ed621b5-e1e5-b13f-b6f6-e50ceed45a93.png)
![１３個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/634c0203-7755-b346-2ec7-624d1a90db47.png)
![14個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/915ccc1c-1b24-6075-f6a8-25417e0e6b18.png)

### <font color="Red">現地点では`localhost:3000`のやつだけで大丈夫です！</font>

**デプロイするときにオリジナル用の設定するの忘れないでください。**

### 一応<font color="Red">http</font>と<font color="Red">https</font>どちらも作っておいてください


`http://localhost:3000/users/auth/google_oauth2/callback`
`https://localhost:3000/users/auth/google_oauth2/callback`

### <font color="Red">デプロイする時に</font><font color="Red">こちらを入力してください</font>
`https://自分のアプリのURL/users/auth/google_oauth2/callback`

### <font color="red">※本番環境では必ず`https`でURIを登録してください！</font>
**※`https`ではなく`http`で登録すると<font color="Red">リダイレクトURIエラー</font>が出ます。**






![１５個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/b3072c93-52b6-d99a-8e1f-26142ce1a88c.png)

#### <font color=Red>発行されたクライアントIDとクライアントシークレットをどこかにメモっといてください。</font>

**以上でGoogle Cloud Platformの設定は終了です**
**見にくい写真ばかりで申し訳ないです:pray:**


# STEP2 いざ実装へ

## 2-1まずはgemを入れましょう！

 <font color="red">**※`gem 'dotenv-rails'`は既に入れてる場合があるので入ってる人は飛ばして大丈夫です！**</font>


```ruby:Gemfile

 gem 'dotenv-rails'
 gem 'omniauth', '1.9.1'
 gem 'omniauth-google-oauth2' 

```

#### ※　`gem 'omniauth'`は最新バージョンだとrailsとの相性が悪いそうなので、安定している` gem 'omniauth', '1.9.1'`を入れてください。

これ知らんくて２時間ぐらい沼りました笑笑

```:コマンドプロンプト
$ bundle install
```

## 2-2 devise.rb追記

`config.omniauth :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET']`

**特に張り付ける場所はどこでもいいですが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']

```

## 2-3 .envと.gitignoreに記述

#### **.envファイルに先ほど取得したクライアントIDとクライアントシークレットを追記します。**

<font color="Red">**.envがないねんけど！！って人は**</font>

写真のように一番下の空間で`右クリック`して`.env`ファイルを作ってあげましょう！！

**※作る階層ミスりがちなのでご注意**

![ここ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/37e230d8-5bb1-aa56-8356-97783a1d9b45.png)

```ruby:.env

GOOGLE_CLIENT_ID=自分のクライアントID
GOOGLE_CLIENT_SECRET=自分のクライアントシークレット

```

### 続いて`.gitignore`の一番下の行に`.env`を記述してください！

```:.gitignore

～省略～

.env

```

## 2-4 routes.rbの編集

**deviseのコントローラを編集するので変更が反映されるように書き換えます！**

```ruby:routes.rb

Rails.application.routes.draw do

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

  # 変更後ここから
  devise_for :users, controllers: {
    
    omniauth_callbacks: "users/omniauth_callbacks"
  }
  # 変更後ここまで

  resources :hoges
  root 'hoges#index'

end

```

## 2-5 userモデルを編集
### <font color="Red">注意事項がいくつかあるのでコピペした後よく読んで下さい！！！</font>

**その１**：コメントアウトのところにも書きましたが、**:validatableの後ろに**<font color="Red">**「,」コンマを忘れないこと**</font>

**その２**：**`ユーザーマイページ`を作成している人、ユーザー情報に`name`、`profile`等のカラムがある人<font color="Red">（要はdeviseのuserカラムに色々追加してる人）</font>**は

`user.追加してるカラム名 = auth.info.追加してるカラム名`
**を追記してあげてください！！**

**<font color="Orange">特別大サービスで
`# user.name = auth.info.name`
`# user.profile = auth.info.profile`
この２つはコメントアウトに書いておいたのでコメントアウトを外すだけでいいですよ！</font>**

### **<font color="Red">※ユーザーマイページを作成している人は注意事項がもう一つあるので記事の最後まで読んで下さい！！</font>**

**パスワード無しで更新する的なやつです。まぁ取り敢えず先に認証実装させましょう。**

```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,
    #「validatable」の後ろにコンマ「,」をつけるのわすれずに↑↑
          :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やprofile を追加している場合は下のコメントアウトを外して使用

      # user.name = auth.info.name
      # user.profile = auth.info.profile
      user.email = auth.info.email
      user.password = Devise.friendly_token[0,20]
    end
  end
  #追記部分ここまで

end

```
## 2-6 マイグレーションファイル作成

認証を行う際に`providerカラム`と、`uidカラム`を使用するのでマイグレーションファイルを作成します。

```:コマンドプロンプト
$ rails g migration AddOuthColumnToUsers provider:string uid:string
```
**その後忘れずに`rails db:migrate`しましょう。**

```:コマンドプロンプト
$ rails db:migrate
```

## 2-6 コントローラー作成・編集

### `controllers/users/omniauth_callbacks_controller.rb` を以下の様に記述してください。

**※<font color="Red">そんなファイルないよ！</font>って人は以下のコマンドを打って作ってください**

```:コマンドプロンプト
$ rails g devise:controllers users
```
作成したら以下の通りに

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

```

※一番上のマジックコメント`# frozen_string_literal: true`も忘れずに入れてください！！

>[なんやねんそれ！って人はこちら](https://qiita.com/YutoYasunaga/items/98111ef50927ecb4135d)

## 2-7 ラスト！登録ボタン作成

**いよいよラストです。
サインインページのボタンを作成しましょう！**

```erb: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 %>


```
**以上で認証の実装自体は終わりです。**

# STEP3　マイページ、ユーザー情報を更新する場合は必読


**先ほど<font color="Red">※ユーザーマイページを作成している人は注意事項がもう一つあるので記事の最後まで読んで下さい！！</font>と書いたと思います。**

**ユーザー情報を更新する時、何をしないといけないですか？？**

![１８個目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/ba862da8-f807-f16e-96f7-0e25e206737d.png)

**そうです！現在のパスワードを入力しないといけません**

ただ今回実装したGoogleアカウントで認証した場合、**ランダムに自動生成**されるようになってしまっています。

```ruby:user.rb
 user.password = Devise.friendly_token[0,20]
```
これです。。。。

こちらを他のカラムの記述同様に書き直してもいいのですが、
**流石に自分のgoogleアカウントのパスワードを晒すのは、、、、**
って感じなので<font color="Red">**解決策として、、、、**</font>


## パスワードなしでマイページを更新できるようにします！

>[基本的にこの記事で実装できますが、混乱する点が多いので解説します！！](https://qiita.com/1992_momotaro/items/d8a220be528a7af69deb)


#### 手順はこの３つ
**1. routes.rbの編集
2. registrations_controller.rbの編集
3. ユーザー編集画面の編集**

## 3-1　routes.rbの編集

**以下のように編集してください！**

**<font color='Red'>※`users/omniauth_callbacks`の後ろに「,」つけるのお忘れなく！！！</font>**

```ruby:routes.rb
  # before
  devise_for :users, controllers: {
    omniauth_callbacks: "users/omniauth_callbacks" 
  }

  #after
  devise_for :users, controllers: {
    omniauth_callbacks: "users/omniauth_callbacks" ,
    registrations: "users/registrations"
  }
```

## 3-2 registrations_controller.rbの編集

**`controllers/users/registrations_controller.rb`を開いてください。**

**40行目付近の`#protected`のコメントアウト外して以下を追記してください。**

```ruby:controllers/users/registrations_controller.rb

 # コメントアウト外す
  protected

  #追記
  def update_resource(resource, params)
    resource.update_without_password(params)
  end

```
## 3-3 これでほんまのほんまにラスト　～パスワード更新関連の記述削除～

**`users/registrations/edit.html.erb`にて以下の記述を削除してください**

```ruby:views/users/registrations/edit.html.erb

  # 以下の記述を削除
  <div class="field">
    <%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
    <% if @minimum_password_length %>
      <br />
      <em><%= @minimum_password_length %> characters minimum</em>
    <% end %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
  </div>

  <div class="field">
    <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
    <%= f.password_field :current_password, autocomplete: "current-password" %>
  </div>

```

**サーバーを立ち上げて動作確認をしてください！**

**参考にさせていただいた記事**
>https://qiita.com/kakki0315/items/b1f0fd10432b273b7e90
https://qiita.com/akioneway94/items/35641ad30c2acb23b562
https://qiita.com/kizakey18/items/aed3c0830c67f19c65a0
https://qiita.com/d0ne1s/items/e1ee23ea23343d6aaa34
https://qiita.com/1992_momotaro/items/d8a220be528a7af69deb
**先人の皆さまありがとうございました。**


**以上で終わりです。お疲れ様でした！何かエラー等あれば連絡してください！！**