登入的帳戶登入

Google 帳戶連結可讓 Google 帳戶持有人輕鬆快速地安全地連結至您的服務,並與 Google 共用資料。

透過「已連結帳戶」功能,使用者只要將自己的 Google 帳戶連結至您的服務,就能啟用「One Google 登入」功能。如此一來,使用者只要按一下滑鼠就能登入,不必重複輸入使用者名稱和密碼。也能降低使用者在服務中建立重複帳戶的機率。

必要條件

如要導入「已連結帳戶」功能,您必須符合下列條件:

  • 您有 Google 帳戶 OAuth 連結實作支援 OAuth 2.0 授權碼流程。您的 OAuth 實作必須包含下列端點:
    • 授權端點來處理授權要求。
    • 憑證端點,以處理存取和重新整理憑證的要求。
    • userinfo 端點可擷取連結使用者的相關基本帳戶資訊;這個資訊會顯示在「已連結帳戶」的登入程序中。
  • 您有 Android 應用程式。

運作方式

前置作業 : 使用者先前已將其「Google 帳戶」與您的服務帳戶建立關聯。

  1. 您可以選擇在「One Tap 登入」流程中顯示已連結帳戶。
  2. 使用者會看到「One Tap 登入」提示,指出您可以透過連結的帳戶登入服務。
  3. 如果使用者選擇繼續使用已連結的帳戶,Google 會傳送憑證到您的端點端點,以便儲存授權碼。要求內含您服務所核發使用者的存取憑證,以及 Google 授權碼。
  4. 將 Google 授權碼提供給 Google ID 憑證,當中包含使用者的 Google 帳戶相關資訊。
  5. 流程完成時,應用程式也會收到 ID 憑證,而您比對的是伺服器中收到的 ID 憑證中的使用者 ID,以便使用者登入您的應用程式。
已連結帳戶。
圖 1.已連結帳戶的登入流程。如果使用者的裝置上有多個登入帳戶,他們可能會看到帳戶選擇工具,而且只有在選取已連結帳戶時,才會進入「已連結帳戶登入」檢視畫面。

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

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

處理 Google 提供的授權碼要求

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

儲存授權碼之前,您必須先驗證「client_id」已獲得 Google 識別的存取憑證。

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 錯誤代碼 (如果要求無效),則傳回 HTTP 200 (OK) 回應。

HTTP 回應

成功

傳回 HTTP 狀態碼 200 OK

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

錯誤

無效的 HTTP 要求時,請以下列其中一種 HTTP 錯誤代碼回應:

HTTP 狀態碼 內文 說明
400 {"error": "invalid_request"} 要求中缺少某個參數,因此伺服器無法繼續處理要求。如果要求包含不支援的參數或重複的參數,也可能會傳回這個屬性
401 {"error": "invalid_request"} 用戶端驗證失敗,例如要求中包含無效的用戶端 ID 或 Secret
401 {"error": "invalid_token"}

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

夥伴存取憑證無效。
403 {"error": "insufficient_permission"}

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

合作夥伴存取權杖未包含執行 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 憑證的 Exchange 授權碼

您必須針對收到的 Google ID 權杖 (當中包含使用者的 Google 帳戶相關資訊) 交換授權碼。

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

要求欄位
client_id 必要 API 的「憑證頁面」。系統通常會使用名為「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,但是此後第三方電子郵件帳戶的所有權可能已更改。