今天接著安裝完成 'omniauth-google-oauth2''omniauth-rails_csrf_protection'這兩個套件之後,我們接續後面的步驟吧。

設定 routes

記得之前用 devise 產生的 controller 中有一個 omniauth_callbacks_controller.rb 這個檔案嗎?
現在可以拿來用了喔,但我們要告訴 devise 要去使用這個 controller 必須要設定好 routes

1
rails g devise:controllers users

如同前面章節有提到,這些產生的 controller 必須要設定好路徑才可以使用喔。如果沒有產生的話可以自己建立 app/controller/users/omniauth_callbacks_controller.rb 到這個路徑。

1
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }

設定 callback controller

這邊是當 google 授權後會帶著得到那邊相關的資料來到我們的網域,就會用 callbacks controller 接下來這些資料,也就是前面填寫給 google 的 已授權的重新導向 url 位置。接下來之後我們要把這些資料拿來比對是否資料庫內已經有對應存在的帳號。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
# 需要在model中實作定義下面 `from_omniauth` 的方法 (app/models/user.rb)
@user = User.from_omniauth(request.env['omniauth.auth'])

if @user.persisted?
flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google'
sign_in_and_redirect @user, event: :authentication
else
session['devise.google_data'] = request.env['omniauth.auth'].except('extra')
redirect_to new_user_registration_url, alert: @user.errors.full_messages.join("\n")
end
end

設定 model

先加入 devise 提供的 :omniauthable 的方法到 model 上面

1
2
3
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable,
:omniauthable, omniauth_providers: [:google_oauth2]

前面在 callback controller 可以看到我們需要對 User 這個 model 定義類別方法 from_omniauth 在 user.rb 中,解析授權回來的資料,並且會從資料庫中比對跟授權回來的 email 資料相同的 user 來建立一個,注意註解下面的部分是處理當沒有對應的 email 或相關註冊填寫的資料時就建立給一個出來進行登入。

如果你定義 user 寫入資料庫的部分有要填入其他欄位或是只要特定的可以自己調整,預設只有 email 跟 password,像我當初專案是多加入 username,所以就改成下面這樣。

1
2
3
4
5
6
7
8
9
10
11
def self.from_omniauth(access_token)
data = access_token.info
user = User.where(email: data['email']).first
# 下面處理是當資料庫內部沒有對應的帳號密碼時,建立給我們專案資料庫去對應每次授權的 token。
user ||= User.create(
(username: data['username'] || data['email'].split('@').first,
email: data['email'],
password: Devise.friendly_token[0,20]
)
user
end

最後可以回去看到 view 的部分

如果你有用他產生預設的 view 應該會直接看到相關連結自動產生在頁面上,你也可以自己找出路徑客製自己藥的東西,可以透過下面找到相關路徑

1
rails routes -c omniauth

填入對應的 link_to 位置應該就可以看到。就可以測試看看是否可以正常使用。

---
參考資料:

  1. YarpslavShmarov 教學影片
  2. omniauth-google-oauth2
  3. Rails 實作第三方登入-Google