Google One Tap を秒で実装する on Rails
GoogleはOne Tapというサインインサービスを提供している。
ユーザのGoogleアカウントを使って他のサービスにサインインできるようになったりプロフィールを共有したりする。サイトにアクセスしたら右上に出てくるやつ。
それをRailsサービスに最速で導入する手引き。
事前準備
GoogleAPIクライアントIDの取得
公式ドキュメントに従ってGoogle Cloud PlatformでOAuth 2.0 Client IDを作って取得する。公式ドキュメントにもある通り、 Authorized JavaScript origins
に localhost
も追加する必要があるのが注意点。
One Tap 表示
まずライブラリを読み込む。全ページに表示させるなら application.html.erb
に入れておく。
<script src="https://accounts.google.com/gsi/client" async defer></script>
次にOne Tapを表示させるコードを入れる。
<div id='g_id_onload'
data-client_id='ここにGoogleAPIクライアントIDを入れる'
data-login_uri='ここにCallBack URLを入れる'
data-prompt_parent_id='g_id_onload'
style='position: fixed; top: 76px; right: 16px;'
data-authenticity_token='<%= form_authenticity_token %>'>
</div>
必須なのはdivのid、クライアントIDそれにCallBack URLだけ。位置を調整するために data-prompt_parent_id
と style
を指定している。
ユーザがOne Tapを利用するとCallBack URLにPOSTリクエストが来る。なのでCSRFトークンを渡すために data-authenticity_token
も指定しておく。
これでOne Tapが表示される。
CallBack
ユーザがOne TapをクリックしてGoogleによる認証が終わった後にアクセスしてくるCallBackエンドポイントを作る。
必要なのはユーザ情報の取得とその情報を使って登録したりログインしたりする処理。登録やログインは各サービスでまちまちなのでここでは割愛。
送られてくるユーザ情報の認証にはgoogleauthを使うと楽。署名とクライアントIDの両方をチェックしてくれる
class GoogleOneTapController < ApplicationController
def callback
payload = Google::Auth::IDTokens.verify_oidc(params[:credential], aud: 'ここにGoogleAPIクライアントIDを入れる')
# 登録・ログイン処理
rescue Google::Auth::IDTokens::SignatureError, Google::Auth::IDTokens::AudienceMismatchError => e
# 署名やクライアントIDが不正な場合の処理
end
end
なお、payloadにはemailやnameが入っている。
cf. クレデンシャル
payload
{
"iss": "https://accounts.google.com", // The JWT's issuer
"nbf": 161803398874,
"aud": "314159265-pi.apps.googleusercontent.com", // Your server's client ID
"sub": "3141592653589793238", // The unique ID of the user's Google Account
"hd": "gmail.com", // If present, the host domain of the user's GSuite email address
"email": "elisa.g.beckett@gmail.com", // The user's email address
"email_verified": true, // true, if Google has verified the email address
"azp": "314159265-pi.apps.googleusercontent.com",
"name": "Elisa Beckett",
// If present, a URL to user's profile picture
"picture": "https://lh3.googleusercontent.com/a-/e2718281828459045235360uler",
"given_name": "Elisa",
"family_name": "Beckett",
"iat": 1596474000, // Unix timestamp of the assertion's creation time
"exp": 1596477600, // Unix timestamp of the assertion's expiration time
"jti": "abc161803398874def"
}
Discussion