使用 OAuth 連結 Google 帳戶

帳戶連結使用業界標準 OAuth 2.0 隱含授權碼流程。您的服務必須支援符合 OAuth 2.0 規定的授權憑證交換端點。

在「暗示」流程中,Google 會在使用者的瀏覽器中開啟您的授權端點。成功登入後,會將長期存取憑證傳回 Google。目前從 Google 發出的每個要求都會包含這個存取憑證。

在「授權碼」流程中,您需要兩個端點:

  • Authorization 端點,可為尚未登入的使用者顯示登入 UI。授權端點也會建立短期的授權碼來記錄使用者。同意要求的存取權。

  • 憑證交換端點,該端點負責兩種交換類型:

    1. 將授權碼提供給長期使用憑證和短期存取憑證。當使用者完成帳戶連結流程時,系統就會執行這個交換作業。
    2. 針對短期存取權杖交換長期更新權杖。 如果 Google 需要這個存取憑證過期,因此需要進行這個交換作業。

選擇 OAuth 2.0 流程

雖然隱含流程比較簡單,但 Google 建議採用隱含流程所核發的存取憑證永遠不會過期。這是因為憑證在隱含流程到期後,必須強制重新連結帳戶。如果您需要基於安全考量而要求憑證過期,強烈建議您改用授權碼流程。

設計指南

本節說明您針對 OAuth 連結流程託管的使用者畫面設計要求和建議。在 Google 應用程式呼叫 API 後,您的平台會向使用者顯示登入 Google 頁面和帳戶連結同意畫面。使用者同意連結帳戶之後,系統就會將他們重新導向 Google 的應用程式。

下圖顯示使用者將 Google 帳戶連結到驗證系統的步驟。第一個螢幕截圖顯示了使用者從平台啟動的連結。第二張圖片則顯示使用者登入 Google 的第三張圖片,第三張圖片則顯示使用者同意授權及確認將自己的 Google 帳戶連結至您的應用程式。最終螢幕截圖顯示 Google app 中成功連結的使用者帳戶。
圖 1.連結 Google 帳戶和同意畫面的帳戶連結。

必要條件

  1. 您必須通知使用者的帳戶將連結至 Google,而不是特定的 Google 產品,例如 Google Home 或 Google 助理。

建議

建議您採取下列做法:

  1. 顯示 Google 的隱私權政策。在同意畫面中加入 Google 隱私權政策連結。

  2. 要分享的資料。使用簡明扼要的用詞告訴使用者 Google 需要哪些資料,以及收集這些資料的原因。

  3. 加入明確的行動號召。在同意畫面上註明明確的行動號召 (例如「同意和連結」)。這是因為使用者必須瞭解需要與 Google 分享哪些資料,才能連結自己的帳戶。

  4. 取消功能:如果使用者選擇不要進行連結,可以提供取消或取消訂閱的方式。

  5. 清除登入程序。確保使用者明確能登入 Google 帳戶,例如使用者名稱和密碼欄位或使用 Google 帳戶登入欄位。

  6. 取消連結。提供機制,讓使用者能取消連結,例如 您平台中帳戶設定的網址。您也可以加入 Google 帳戶連結,方便使用者管理已連結帳戶。

  7. 可變更使用者帳戶。建議使用者切換帳戶的方法。如果使用者經常擁有多個帳戶,這項功能就特別實用。

    • 如果使用者必須先關閉同意畫面才能切換帳戶,請將可復原的錯誤傳送給 Google,讓使用者可透過 OAuth 連結隱含流程登入所需帳戶。
  8. 加入您的標誌。在同意畫面中顯示公司標誌。 請善用樣式指南來放置標誌。如果您希望一併顯示 Google 的標誌,請參閱標誌和商標一文。

创建项目

如需创建项目以使用帐号关联,请按以下步骤操作:

  1. Go to the Google API Console.
  2. 單擊創建項目
  3. 輸入名稱或接受生成的建議。
  4. 確認或編輯所有剩餘字段。
  5. 點擊創建

要查看您的項目ID:

  1. Go to the Google API Console.
  2. 在登錄頁面的表格中找到您的項目。項目ID出現在ID列中。

Google 帐号关联流程包括一个同意屏幕,用于告知用户请求访问其数据的应用、用户要求的数据类型以及适用的条款。您需要先配置 OAuth 权限请求页面,然后才能生成 Google API 客户端 ID。

  1. 打开 Google API 控制台的 OAuth 同意屏幕页面。
  2. 如果出现提示,请选择您刚刚创建的项目。
  3. 在“OAuth 同意屏幕”页面上,填写表单,然后点击“保存”按钮。

    应用名称:请求用户同意的应用的名称。该名称应准确反映您的应用,并与用户在别处看到的应用名称保持一致。应用名称将显示在帐号关联同意屏幕上。

    应用徽标:同意屏幕上的图片,有助于用户识别您的应用。徽标会显示在帐号关联同意屏幕和帐号设置

    支持电子邮件地址:供用户就其同意情况与您联系。

    Google API 的范围:范围允许您的应用访问用户的私有 Google 数据。对于 Google 帐号关联用例,默认范围(电子邮件、个人资料、OpenID)就足够了,您无需添加任何敏感范围。最佳做法一般是在需要访问时逐步请求作用域,而不是预先请求。了解详情

    已获授权的网域:为保护您和您的用户,Google 仅允许使用 OAuth 进行身份验证的应用使用已获授权的网域。您应用的链接必须托管在已获授权的网域上。了解详情

    应用首页链接:您的应用的首页。必须托管在已获授权的网域上。

    应用隐私权政策链接:在 Google 帐号关联同意屏幕上显示。必须托管在已获授权的网域上。

    应用服务条款链接(可选):必须托管在已获授权的网域上。

    图 1. 一款虚构应用 Tunery 的 Google 帐号关联同意屏幕

  4. 查看“验证状态”。如果您的申请需要验证,请点击“提交验证”按钮,提交您的申请。如需了解详情,请参阅 OAuth 验证要求

實作 OAuth 伺服器

授權碼流的的OAuth 2.0服務器實現由兩個端點,通過HTTPS,你的服務使可用的。第一個端點是授權端點,它負責查找或獲得用戶對數據訪問的同意。授權端點向尚未登錄的用戶顯示登錄 UI,並記錄對請求訪問的同意。第二個端點是令牌交換端點,用於獲取加密字符串,稱為令牌,授權用戶訪問您的服務。

當 Google 應用程序需要調用您的服務的某個 API 時,Google 會結合使用這些端點來獲得您的用戶的許可,以代表他們調用這些 API。

Google發起的一次OAuth 2.0授權碼流會話流程如下:

  1. Google 在用戶的瀏覽器中打開您的授權端點。如果流程在 Action 的純語音設備上開始,Google 會將執行轉移到手機。
  2. 用戶登錄(如果尚未登錄)並授予 Google 使用您的 API 訪問其數據的權限(如果他們尚未授予權限)。
  3. 您的服務創建一個授權碼,並返回給谷歌。為此,請將用戶的瀏覽器重定向回 Google,並將授權代碼附加到請求中。
  4. 谷歌發送授權代碼,您的令牌交換終結,從而驗證代碼的真實性,並返回一個訪問令牌刷新令牌。訪問令牌是一個短期令牌,您的服務接受它作為訪問 API 的憑據。刷新令牌是一個長期存在的令牌,Google 可以存儲它並在它們到期時使用它來獲取新的訪問令牌。
  5. 用戶完成帳戶關聯流程後,從 Google 發送的每個後續請求都包含一個訪問令牌。

處理授權請求

當您需要使用 OAuth 2.0 授權代碼流執行帳戶關聯時,Google 會將用戶發送到您的授權端點,並發送一個包含以下參數的請求:

授權端點參數
client_id您分配給 Google 的客戶 ID。
redirect_uri您向其發送對此請求的響應的 URL。
state傳遞回 Google 的簿記值在重定向 URI 中保持不變。
scope可選:以空格分隔的集合,其指定谷歌正在請求授權的數據範圍的字符串。
response_type要在響應中返回的值的類型。對於的OAuth 2.0授權碼流,響應類型總是code
user_locale在谷歌帳戶語言設置RFC5646格式,用於本地化用戶的首選語言內容。

例如,如果您的授權端點可在https://myservice.example.com/auth ,請求看起來像下面這樣:

GET https://myservice.example.com/auth?client_id=GOOGLE_CLIENT_ID&redirect_uri=REDIRECT_URI&state=STATE_STRING&scope=REQUESTED_SCOPES&response_type=code&user_locale=LOCALE

對於處理登錄請求的授權端點,請執行以下步驟:

  1. 驗證client_id您分配給谷歌的客戶ID匹配,並且該redirect_uri由谷歌為您服務提供的重定向URL匹配。這些檢查對於防止授予對意外或配置錯誤的客戶端應用程序的訪問權限非常重要。如果你支持多種OAuth 2.0流程的,也確認response_typecode
  2. 檢查用戶是否已登錄您的服務。如果用戶未登錄,請完成服務的登錄或註冊流程。
  3. 生成供 Google 用於訪問您的 API 的授權代碼。授權碼可以是任何字符串值,但必須唯一代表用戶、token所針對的客戶端、授權碼的過期時間,並且不能被猜到。您通常會發出大約 10 分鐘後過期的授權代碼。
  4. 確認URL指定由redirect_uri參數有以下形式:
      https://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID
      https://oauth-redirect-sandbox.googleusercontent.com/r/YOUR_PROJECT_ID
      
  5. 重定向用戶的瀏覽器由指定的URL redirect_uri參數。當你通過附加重定向包括剛剛生成授權碼和原始未修正的狀態值codestate參數。以下是所得的URL的一個示例:
    https://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID?code=AUTHORIZATION_CODE&state=STATE_STRING

處理令牌交換請求

您的服務的令牌交換端點負責兩種令牌交換:

  • 交換訪問令牌和刷新令牌的授權代碼
  • 交換刷新令牌以獲取訪問令牌

令牌交換請求包括以下參數:

令牌交換端點參數
client_id將請求源標識為 Google 的字符串。此字符串必須在您的系統中註冊為 Google 的唯一標識符。
client_secret您在 Google 上為您的服務註冊的秘密字符串。
grant_type正在交換的令牌類型。這是不是authorization_coderefresh_token
codegrant_type=authorization_code ,這個參數是從您登錄或令牌交換終結收到谷歌的代碼。
redirect_urigrant_type=authorization_code ,該參數是在初始授權請求中使用的URL。
refresh_tokengrant_type=refresh_token ,這個參數是令牌從令牌交換終結收到谷歌的刷新。
交換訪問令牌和刷新令牌的授權代碼

在用戶登錄並且您的授權端點向 Google 返回一個短期授權代碼後,Google 會向您的令牌交換端點發送請求,以交換訪問令牌和刷新令牌的授權代碼。

對於這些請求,價值grant_typeauthorization_code ,和值code是您先前授予給谷歌授權碼的值。以下是為訪問令牌和刷新令牌交換授權代碼的請求示例:

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

client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=REDIRECT_URI

要為訪問Exchange授權碼令牌和刷新令牌,您的令牌交換終結響應POST通過執行以下步驟要求:

  1. 驗證該client_id識別為授權原點,並且所述請求源client_secret預期值相匹配。
  2. 驗證授權碼是否有效且未過期,以及請求中指定的客戶端 ID 是否與與授權碼關聯的客戶端 ID 匹配。
  3. 確認URL中指定由redirect_uri參數是相同的初始授權請求中使用的值。
  4. 如果您無法驗證所有的上述標準,則返回一個HTTP 400錯誤的請求錯誤與{"error": "invalid_grant"}作為身體。
  5. 否則,使用授權代碼中的用戶 ID 生成刷新令牌和訪問令牌。這些令牌可以是任何字符串值,但它們必須唯一地代表令牌所針對的用戶和客戶端,並且不能被猜測。對於訪問令牌,還要記錄令牌的到期時間,通常是您發出令牌後的一個小時。刷新令牌不會過期。
  6. 返回以下JSON對象在HTTPS響應的主體:
    {
    "token_type": "Bearer",
    "access_token": "ACCESS_TOKEN",
    "refresh_token": "REFRESH_TOKEN",
    "expires_in": SECONDS_TO_EXPIRATION
    }
    

Google 為用戶存儲訪問令牌和刷新令牌,並記錄訪問令牌的到期時間。當訪問令牌過期時,Google 使用刷新令牌從您的令牌交換端點獲取新的訪問令牌。

交換刷新令牌以獲取訪問令牌

當訪問令牌過期時,Google 會向您的令牌交換端點發送請求,以將刷新令牌交換為新的訪問令牌。

對於這些請求,價值grant_typerefresh_token ,和值refresh_token是令牌先前授予谷歌刷新的值。以下是將刷新令牌交換為訪問令牌的請求示例:

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

client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

要交換令牌的訪問令牌刷新,您的令牌交換終結響應POST通過執行以下步驟要求:

  1. 驗證client_id標識請求起源谷歌,那client_secret預期值相符。
  2. 驗證刷新令牌是否有效,以及請求中指定的客戶端 ID 是否與與刷新令牌關聯的客戶端 ID 匹配。
  3. 如果您無法驗證所有的上述標準,則返回一個HTTP 400錯誤的請求錯誤與{"error": "invalid_grant"}作為身體。
  4. 否則,使用刷新令牌中的用戶 ID 生成訪問令牌。這些令牌可以是任何字符串值,但它們必須唯一地代表令牌所針對的用戶和客戶端,並且不能被猜測。對於訪問令牌,還要記錄令牌的到期時間,通常是在您發出令牌後的一個小時。
  5. 在 HTTPS 響應的正文中返回以下 JSON 對象:
    {
    "token_type": "Bearer",
    "access_token": " ACCESS_TOKEN ",
    "expires_in": SECONDS_TO_EXPIRATION
    }
Handle userinfo requests

The userinfo endpoint is an OAuth 2.0 protected resource that return claims about the linked user. Implementing and hosting the userinfo endpoint is optional, except for the following use cases:

After the access token has been successfully retrieved from your token endpoint, Google sends a request to your userinfo endpoint to retrieve basic profile information about the linked user.

userinfo endpoint request headers
Authorization header The access token of type Bearer.

For example, if your userinfo endpoint is available at https://myservice.example.com/userinfo, a request might look like the following:

GET /userinfo HTTP/1.1
Host: myservice.example.com
Authorization: Bearer ACCESS_TOKEN

For your userinfo endpoint to handle requests, do the following steps:

  1. Extract access token from the Authorization header and return information for the user associated with the access token.
  2. If the access token is invalid, return an HTTP 401 Unauthorized error with using the WWW-Authenticate Response Header. Below is an example of a userinfo error response:
    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: error="invalid_token",
    error_description="The Access Token expired"
    
    If a 401 Unauthorized, or any other unsuccessful error response is returned during the linking process, the error will be non-recoverable, the retrieved token will be discarded and the user will have to initiate the linking process again.
  3. If the access token is valid, return and HTTP 200 response with the following JSON object in the body of the HTTPS response:

    {
    "sub": "USER_UUID",
    "email": "EMAIL_ADDRESS",
    "given_name": "FIRST_NAME",
    "family_name": "LAST_NAME",
    "name": "FULL_NAME",
    "picture": "PROFILE_PICTURE",
    }
    
    If your userinfo endpoint returns an HTTP 200 success response, the retrieved token and claims are registered against the user's Google account.

    userinfo endpoint response
    sub A unique ID that identifies the user in your system.
    email Email address of the user.
    given_name Optional: First name of the user.
    family_name Optional: Last name of the user.
    name Optional: Full name of the user.
    picture Optional: Profile picture of the user.

驗證實作

您可以通過使用驗證實現的OAuth 2.0遊樂場工具。

在工具中,執行以下步驟:

  1. 單擊配置打開的OAuth 2.0配置窗口。
  2. OAuth流場中,選擇客戶端
  3. OAuth端點字段中,選擇自定義
  4. 在相應字段中指定您的 OAuth 2.0 端點和您分配給 Google 的客戶端 ID。
  5. 步驟1部分,不要選擇任何谷歌範圍。相反,將此字段留空或鍵入對您的服務器有效的範圍(如果不使用 OAuth 範圍,則輸入任意字符串)。當您完成後,單擊授權的API。
  6. 步驟2步驟3段,完成OAuth 2.0流程和驗證每個步驟按預期工作。

您可以通過驗證您的實現谷歌帳戶鏈接演示工具。

在工具中,執行以下步驟:

  1. 點擊登錄在與谷歌按鈕。
  2. 選擇您要關聯的帳戶。
  3. 輸入服務標識。
  4. (可選)輸入您將請求訪問的一個或多個範圍。
  5. 單擊開始演示
  6. 出現提示時,確認您可以同意並拒絕鏈接請求。
  7. 確認您被重定向到您的平台。