使用 OAuth 連結 Google 帳戶

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

隐式流程中,Google 会在用户的浏览器中打开您的授权端点。成功登录后,系统会将长期访问令牌返回到 Google。现在,从 Google 发送的每个请求中都包含此访问令牌。

授权代码流程中,您需要两个端点:

  • 授权端点 - 向尚未登录的用户显示登录界面。授权端点还会创建一个短期授权代码,用于记录用户针对所请求的访问权限的同意情况。

  • 令牌交换端点,负责两种交换类型:

    1. 将授权代码交换为长期刷新令牌和短期访问令牌。这种交换会在用户完成帐号关联流程时进行。
    2. 将长期有效的刷新令牌交换为短期访问令牌。当 Google 需要新的访问令牌时,由于此令牌已过期,因此出现这种交换。

选择 OAuth 2.0 流程

虽然隐式数据流的实现过程更简单,但 Google 建议隐式数据流签发的访问令牌永远不会过期。这是因为在令牌随隐式流程过期后,用户被迫再次关联自己的帐号。出于安全考虑,如果您需要令牌过期,我们强烈建议您改为使用授权代码流程。

设计准则

本部分将介绍针对 OAuth 关联流程托管的用户屏幕的设计要求和建议。在由 Google 的应用调用后,您的平台会向用户显示“登录 Google”页面和帐号关联屏幕。用户同意关联帐号后,会被重定向回 Google 的应用。

此图显示了用户将其 Google 帐号与身份验证系统关联的步骤。第一个屏幕截图显示了用户从您的平台发起的关联。第二张图片展示了用户登录 Google 的界面,第三张图片显示了用户同意将其 Google 帐号与应用关联的确认消息。最后的屏幕截图显示的是已成功在 Google 应用中关联的用户帐号。
图 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
    }
处理用户信息请求

用户信息终端是一个OAuth 2.0保护的资源,对链接的用户返回的权利要求。实现和托管 userinfo 端点是可选的,以下用例除外:

从您的令牌端点成功检索访问令牌后,Google 会向您的 userinfo 端点发送请求,以检索有关链接用户的基本个人资料信息。

userinfo 端点请求标头
Authorization header Bearer 类型的访问令牌。

例如,如果你的用户信息终端可在https://myservice.example.com/userinfo ,请求看起来像下面这样:

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

要让您的 userinfo 端点处理请求,请执行以下步骤:

  1. 从 Authorization 标头中提取访问令牌并返回与访问令牌关联的用户的信息。
  2. 如果访问令牌无效,返回HTTP 401错误未经授权使用的WWW-Authenticate响应头。下面是一个userinfo的错误响应的一个示例:
    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: error="invalid_token",
    error_description="The Access Token expired"
    
    如果一个401未经授权,或任何其它不成功错误响应在关联过程返回时,误差将是不可恢复的,所检索的令牌将被丢弃,并且用户将必须再次启动链接过程。
  3. 如果访问令牌是有效的,回国与以下JSON对象在HTTPS响应的身体HTTP 200回应:

    {
    "sub": "USER_UUID",
    "email": "EMAIL_ADDRESS",
    "given_name": "FIRST_NAME",
    "family_name": "LAST_NAME",
    "name": "FULL_NAME",
    "picture": "PROFILE_PICTURE",
    }
    
    如果你的用户信息端点返回一个HTTP 200成功响应,检索到的令牌和索赔登记针对用户的谷歌帐户。

    用户信息端点响应
    sub标识系统中用户的唯一 ID。
    email用户的电子邮件地址。
    given_name可选:用户的名字。
    family_name可选:用户的姓氏。
    name可选:用户的全名。
    picture可选:用户的档案图片。

驗證實作

您可以通過使用驗證實現的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. 確認您被重定向到您的平台。