使用 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. 确认您被重定向到您的平台。