【Rails】Googleログイン実装〜Herokuデプロイまでの道のり

`gem omniauth-google-oauth2`を使いつつGoogleログインを実装し、Herokuでデプロイすることまでの道のりを書きます。
途中途中でエラーが出たので、その辺りも書いていきます。

# ローカルでの実装編

ローカルで実装する手順をまずは書きます。

## GoogleクライアントID、クライアントシークレットの取得

https://console.developers.google.com/project

![リソースの管理_-_Google_API_コンソール.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348703/a3dc2776-713f-d8aa-d548-20432ec5ede0.jpeg)
⬇︎
![新しいプロジェクト_–_saythanksapp_–_Google_API_Console.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348703/b077ee27-f0b9-ea52-a08f-c5199d0f779c.jpeg)
⬇︎
![同意画面_-_saythanksapp_-_Google_API_コンソール.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348703/ec1e8479-ee62-d148-8cea-b09ef0319b46.jpeg)
⬇︎
![同意画面_-_saythanksapp_-_Google_API_コンソール.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348703/1bc89785-e8bf-9a07-0b30-660d2e712ee6.jpeg)
⬇︎(保存)
![認証情報_-_practiceproject_-_Google_API_コンソール.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348703/3cac6e95-a5c7-8b90-df86-99a8e16a470b.jpeg)

⬇︎

![OAuth_クライアント_ID_の作成_-_practiceproject_-_Google_API_コンソール.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348703/fd586607-6b7e-6cd2-491a-e4ccb2600afc.jpeg)

▼承認済みのリダイレクトURIに入れる値

- `http://localhost:3000/users/auth/google/callback`
- `アプリのURL/users/auth/google/callback`(ex.`https://say-thank-u.herokuapp.com/users/auth/google/callback`)

上記の流れで発行される、`クライアントID`と`クライアントシークレット`をメモ帳などに控えておきます。

## Deviseの導入

Deviseを導入する手順です。順番を間違えると面倒なのでお気をつけください。

```ruby:Gemfile
gem 'devise'
gem 'omniauth'
gem 'omniauth-google-oauth2'
```

```
$ bundle install
```

```
$ rails g devise:install
```

```
$ rails g devise user
```

```ruby:devise_create_user.rb

      #add
      t.string :users, :name
      t.string :users, :password
      t.string :users, :provider
      t.string :users, :uid
      t.string :users, :meta
      t.string :users, :reset_password_token
      t.string :users, :reset_password_sent_at
      t.string :users, :remember_created_at
      #以下はコメントアウトされている場合は解除してください
      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip
```

Userテーブルが存在している場合には、migrationファイルの中身について、上記のカラムが追加されるように書き換える必要があります。

```
$ rake db:migrate
```

## modelを修正

```ruby:app/model/user.rb
class User < ActiveRecord::Base
  devise :trackable, :omniauthable, omniauth_providers: %i(google)

  protected
  def self.find_for_google(auth)
    user = User.find_by(email: auth.info.email)

    unless user
      user = User.create(name:     auth.info.name,
                         email: auth.info.email,
                         provider: auth.provider,
                         uid:      auth.uid,
                         token:    auth.credentials.token,
                         password: Devise.friendly_token[0, 20],
                         meta:     auth.to_yaml)
    end
    user
  end
end

```

## config修正

今回は`.env`にGOOGLE_APP_IDなどを書き込むので、それらの準備をします。

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

```
$ bundle install
```

`.env`を作成してください。

```ruby:.env
GOOGLE_APP_ID='クライアントIDをペースト'
GOOGLE_APP_SECRET='-クライアントシークレットをペースト'
```

```ruby:.gitignore
/.env #追記
```

さて`config`を修正します。

```ruby:config/initializers/devise.rb
Devise.setup do |config|
  require 'devise/orm/active_record'
  config.omniauth :google_oauth2,
                  ENV['GOOGLE_APP_ID'], 
                  ENV['GOOGLE_APP_SECRET'], 
                  name: :google
end
```

## ログインリンク設置

```ruby:login_form.html.erb
<%= link_to 'Googleログイン',  user_google_omniauth_authorize_path %>
```

## routes.rbの修正

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

## controllerの作成・修正

```ruby:app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def google
    @user = User.find_for_google(request.env['omniauth.auth'])

    if @user.persisted?
      flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google'
      sign_in_and_redirect @user, event: :authentication
      session[:user_id] = @user.id #add
    else
      session['devise.google_data'] = request.env['omniauth.auth']
      redirect_to new_user_registration_url
    end
  end
end

```

ここまでの実装が完了したら、`rails s`を叩くとローカルでは問題なく動くはずです。

`Not found. Authentication passthru.`などが表示された場合は、[ログインリンクの実装](https://qiita.com/drafts/c10a5642afbee93a961a/edit#%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%83%AA%E3%83%B3%E3%82%AF%E8%A8%AD%E7%BD%AE)のところが間違っている可能性があるので、見直してください。


# Herokuへのデプロイで`Precompiling assets failed`が出た場合

上記の手順でローカルでは問題なく動いても、`git push heroku master`を実行した際に、`Precompiling assets failed`というエラーが出ることがあります。

この際の対処法を書いておきます。

まずは以下のコマンドで表示される`secret_key_base`をコピーします。

```
$ EDITOR=vim rails credentials:edit
```

コピーした文字列を以下の箇所に貼り付けします。

```ruby:.env
  SECRET_KEY_BASE = 'ここにペースト'
```

```ruby:config/initializers/devise.rb

 config.secret_key = ENV['SECRET_KEY_BASE'] #コメントアウトを外す

```
これで一旦Herokuへのデプロイ`git push heroku master`コマンドは通ります。しかし、`.gitignore`で`.env`ファイルはGitにあげない設定にしてあるので、Heroku側で改めて変数を設定する必要があります。

### git push heroku master後にやること

```
$ heroku config:set GOOGLE_APP_ID='appidを貼り付け'
$ heroku config:set GOOGLE_APP_ID='secretを貼り付け'
$ heroku config:set SECRET_KEY_BASE='secret_key_baseを貼り付け'
$ heroku run rails db:migrate
```


色々試してみた中でこれが結果的にうまくいったのですが、なぜうまくいったのか理解してません。フィードバックをコメント欄などで頂けますと幸いです🙇‍♂️

# 参考
[爆速ッ!! gem omniauth-google-oauth2 で認証させる](https://qiita.com/bino98/items/596b5cffeca7c104bd90#%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8Bapi%E3%81%AE%E8%A8%AD%E5%AE%9A)
[rakeがDevise.secret_key was not setと出て失敗するときの対処法](https://hacknote.jp/archives/7992/)