Rails googleを使ったSNS認証

# ゴール
googole認証のリンクをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/44b1daf5-de4a-e096-fade-e8a3d7aef1fe.png)

アカウントを選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/63dcec9e-49b1-cc36-7876-ff761c17156f.png)

**認証成功!!**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/e2bb848c-f69a-3b77-eaf6-59c3058f968d.png)



#ベースの作成
- deviseを導入する
- scaffoldで投稿機能を作成
![ezgif.com-video-to-gif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/a17fb807-23c2-03ee-d339-02d61b26acaa.gif)

ログインして、投稿を作成できるアプリケーションを作成しました。

#googleの設定をする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/5aaf7b6b-431a-e5e6-8a4d-6e4873384b01.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/e42bf82f-bc16-ffb3-4bef-754ef3fe7e04.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/3e9e3260-c10d-622c-fee0-b85bb5825371.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/2f4ab20c-80c3-1998-a42b-8e4f2b42b146.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/52abb6bb-4ae4-4114-dc37-d5e8467a7acb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/d7e1b81c-cd10-557b-d09b-f0b111a0a3e4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/d5e0851f-10e7-57e5-fa3c-2dd75e63bc92.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/b5f1dfa7-78a4-0672-af53-f30be6b53634.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/f7aa7119-096e-5645-7f2d-fb60f716e111.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/b2e3c48a-3e7c-90bc-5678-6551a17ef7cd.png)
URLは開発環境の場合、こちらを入力してください
`http://localhost:3000/users/auth/google_oauth2/callback`
本番環境でも使われる場合は、こちらを入力してください
`http://本番環境URL/users/auth/google_oauth2/callback`


#コード編集していきます
環境変数の設定をします。

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

私は環境変数の管理に`dotenv-rails`を使用しました。

```ruby:gemfile
gem 'dotenv-rails'
```

`bundle install`します。
アプリケーションのルートディレクトリ直下に`.env`を作成します

以下の`クライアントID`,`クライアントシークレット`をコピーして

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390288/0e6ba952-1bed-9169-1b6f-7a17778465e0.png)

`.env`に以下のように貼り付けします

```ruby:.env
GOOGLE_CLIENT_ID='クライアントIDを入力'
GOOGLE_CLIENT_SECRET='クライアント シークレット'
```

環境変数は、githubにpushする場合は`.env`を`.ignore`に追加しておくと良いかと思います。

```ruby:.ignore
# 以下を追記
.env
```

# gemfile編集

```ruby:gemfile
gem 'omniauth-google-oauth2'
```

上記のgemを追加して

`bundle install`

# ルーティング編集
```ruby:gemfile
Rails.application.routes.draw do
  # deviseのコントローラを編集するときは以下を記述しないと変更が反映されないので注意
  devise_for :users, controllers: {
    # deviseの階層を編集した場合は適宜pathを編集してください
    omniauth_callbacks: "users/omniauth_callbacks"
  }

  resources :posts

  root 'posts#index'
end

```

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

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

`rails db:migrate`

# userモデルを編集
`user.rb`に処理を書いていきます

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

ここで出てくる`first_or_create`が初めて使うメソッドでした。
結構便利だなと、、、

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

一度`rails console -s`などを使っていろいろ試してみると良いかと！
`rails console -s`を使えばデータベースに変更が加わらないので安心です。

# omniauthの処理を編集します
```ruby: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

```

以上でgoogleでsns認証ができるかと思います！！


# 参考
[Facebook/Twitter/Googleでのユーザー登録をDevise & Omniauthを使って爆速で実装する]
(https://qiita.com/kazuooooo/items/47e7d426cbb33355590e)