連結帳戶登入

Google 帳戶連結功能可讓 Google 帳戶持有人快速、順暢又安全地連線至您的服務,並與 Google 共用資料。

「已連結帳戶登入」功能會為已將 Google 帳戶連結至您的服務的使用者,啟用 One Tap 登入 Google 功能。使用者只要按一下滑鼠即可登入,不必重新輸入使用者名稱和密碼,因此享有更優質的使用體驗。同時降低使用者在您的服務中建立重複帳戶的機率。

需求條件

您必須符合下列條件,才能導入已連結帳戶的登入功能:

  • 您的 Google 帳戶 OAuth 連結實作支援 OAuth 2.0 授權碼流程。您的 OAuth 實作必須包含下列端點:
    • 授權端點來處理授權要求。
    • 權杖端點,處理存取及更新權杖的要求。
    • userinfo 端點:擷取已連結使用者的基本帳戶資訊,在「已連結帳戶」登入過程中向使用者顯示。
  • 您擁有 Android 應用程式。

運作方式

必要條件 :使用者先前已將自己的 Google 帳戶與您服務中的帳戶建立連結。

  1. 您可以選擇在 One Tap 登入流程中顯示已連結帳戶。
  2. 系統會向使用者顯示 One Tap 登入提示,讓他們選擇透過已連結帳戶登入服務。
  3. 如果使用者選擇繼續透過已連結帳戶繼續操作,Google 就會傳送要求給您的權杖端點,以便儲存授權碼。這類要求包含由您服務核發的使用者存取權杖,以及 Google 授權碼。
  4. 您將 Google 授權碼交換給包含使用者 Google 帳戶相關資訊的 Google ID 權杖。
  5. 應用程式也會在流程結束時收到 ID 權杖,並將此權杖與伺服器收到的 ID 權杖中的使用者 ID 進行比對,以便使用者登入應用程式。
連結帳戶的登入。
圖 1.已連結帳戶的登入流程。如果使用者的裝置上有多個已登入帳戶的帳戶,使用者可能會看到帳戶選擇工具,而只有在選取已連結帳戶時,才會前往「已連結帳戶登入」檢視畫面。

在 Android 應用程式中實作已連結帳戶登入功能

如要在 Android 應用程式中支援已連結帳戶登入,請按照 Android 導入指南中的指示操作。

處理 Google 發出的授權碼要求

Google 向您的權杖端點發出 POST 要求,以儲存您交換使用者 ID 權杖的授權碼。這項要求包含使用者的存取權杖和 Google 核發的 OAuth2 授權碼。

儲存授權碼之前,您必須先驗證已授予 Google (由 client_id 識別) 的存取權杖。

HTTP 要求

要求範例

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

code=GOOGLE_AUTHORIZATION_CODE
&grant_type=urn:ietf:params:oauth:grant-type:reciprocal
&client_id=CLIENT_ID
&client_secret=CLIENT_SECRET
&access_token=ACCESS_TOKEN

權杖交換端點必須能處理下列要求參數:

權杖端點參數
code 必要的 Google OAuth2 授權碼
client_id 您必須向 Google 核發的必填用戶端 ID
client_secret 您向 Google 核發的必要用戶端密鑰
access_token 必填:您核發給 Google 的存取權杖。您將使用這項資訊來瞭解使用者的背景
grant_type 必要 值必須設為 urn:ietf:params:oauth:grant-type:reciprocal

權杖交換端點應按照下列步驟回應 POST 要求:

  • 確認 client_id 已授予 Google 指定的「access_token」。
  • 如果要求有效,且驗證碼已成功交換 Google ID 權杖,則回應以 HTTP 200 (OK) 回應;如果要求無效,則傳回 HTTP 錯誤代碼。

HTTP 回應

成功

傳回 HTTP 狀態碼 200 OK

成功回應範例
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{}

錯誤

如果 HTTP 要求無效,請回應下列其中一個 HTTP 錯誤代碼:

HTTP 狀態碼 Body 說明
400 {"error": "invalid_request"} 要求缺少參數,因此伺服器無法處理要求。如果要求包含不支援的參數或重複指定參數,也可能會傳回這個錯誤。
401 {"error": "invalid_request"} 用戶端驗證失敗,例如要求包含無效的用戶端 ID 或密鑰
401 {"error": "invalid_token"}

在回應標頭中加入「WWW-Authentication: Bearer」驗證驗證

合作夥伴存取權杖無效。
403 {"error": "insufficient_permission"}

在回應標頭中加入「WWW-Authentication: Bearer」驗證驗證

合作夥伴存取權杖未包含執行 Reciprocal OAuth 所需的範圍
500 {"error": "internal_error"} 伺服器發生錯誤

錯誤回應應包含下列欄位:

錯誤回應欄位
error 必要錯誤字串
error_description 使用者可理解的錯誤說明
error_uri 提供錯誤詳情的 URI
錯誤 400 回應範例
HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "error": "invalid_request",
  "error_description": "Request was missing the 'access_token' parameter."
}

ID 權杖交換授權碼

您必須以收到的授權碼換取含有使用者 Google 帳戶相關資訊的 Google ID 權杖。

如要交換 Google ID 權杖的授權碼,請呼叫 https://oauth2.googleapis.com/token 端點並設定下列參數:

要求欄位
client_id 必填:從 API 控制台的「憑證」頁面取得的用戶端 ID。這通常是名稱為「New Actions on Google App」的憑證
client_secret 必要:從 API 控制台的「憑證」頁面取得的用戶端密鑰
code 必填:初始要求中傳送的授權碼
grant_type 必填如 OAuth 2.0 規格所定義,這個欄位的值必須設為 authorization_code
要求範例
POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=GOOGLE_AUTHORIZATION_CODE
&grant_type=authorization_code
&client_id=GOOGLE_CLIENT_ID
&client_secret=GOOGLE_CLIENT_SECRET

Google 回應這項要求時,會傳回包含短期存取權杖和更新權杖的 JSON 物件。

回應會包含以下欄位:

回覆欄位
access_token Google 核發的存取權杖。您的應用程式會傳送這個權杖來授權 Google API 要求。
id_token ID 權杖包含使用者的 Google 帳戶資訊。「驗證回應」部分詳細說明如何解碼及驗證 ID 權杖回應
expires_in 存取權杖的剩餘生命週期 (以秒為單位)
refresh_token 可用來取得新存取權杖的權杖。更新權杖的效力會持續到使用者撤銷存取權為止
scope 針對「已連結帳戶登入」使用情境,這個欄位的值一律會設為 openid
token_type 傳回的權杖類型。目前這個欄位的值一律會設為 Bearer
回應範例
HTTP/1.1 200 OK
Content-type: application/json; charset=utf-8

{
  "access_token": "Google-access-token",
  "id_token": "Google-ID-token",
  "expires_in": 3599,
  "token_type": "Bearer",
  "scope": "openid",
  "refresh_token": "Google-refresh-token"
}


POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=Google authorization code
&grant_type=authorization_code
&client_id=Google client id
&client_secret=Google client secret

驗證「ID 權杖」回應

驗證並解碼JWT斷言

您可以使用針對您的語言JWT解碼庫來驗證和解碼JWT斷言。使用Google的JWKPEM格式的公鑰來驗證令牌的簽名。

解碼後,JWT斷言類似於以下示例:

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

除了驗證令牌的簽名外,還要驗證斷言的頒發者( iss字段)為https://accounts.google.com ,受眾( aud字段)是您分配的客戶端ID,並且令牌尚未過期( exp場地)。

使用emailemail_verifiedhd字段,您可以確定Google是否託管電子郵件地址並對其具有權威性。如果Google具有權威性,則當前已知該用戶為合法帳戶所有者,您可以跳過密碼或其他挑戰方法。否則,可以使用這些方法在鏈接之前驗證帳戶。

Google具有權威性的情況:

  • email後綴為@gmail.com ,這是一個Gmail帳戶。
  • email_verified為true並且設置了hd ,這是一個G Suite帳戶。

用戶可以在不使用Gmail或G Suite的情況下註冊Google帳戶。如果email不包含@gmail.com後綴,並且hd缺失,則Google不具有權威性,建議使用密碼或其他挑戰方法來驗證用戶。當Google在創建Google帳戶時最初驗證了用戶時, email_verfied也可能為true,但是此後第三方電子郵件帳戶的所有權可能已更改。