关联的帐号登录

借助 Google 账号关联功能,Google 账号持有者可以快速、顺畅且安全地关联到您的服务,并与 Google 分享数据。

关联的账号登录功能可为已将 Google 账号与您的服务相关联的用户启用一键式 Google 登录。这样可以改善用户体验,因为用户只需点击一下即可登录,而无需重新输入用户名和密码。这还可以降低用户在您的服务中创建重复账号的几率。

要求

如需实现关联的账号登录,您必须满足以下要求:

  • 您实现了支持 OAuth 2.0 授权代码流程的 Google 账号 OAuth 关联。您的 OAuth 实现必须包含以下端点:
    • 用于处理授权请求的授权端点
    • 用于处理访问令牌和刷新令牌请求的令牌端点
    • userinfo 端点用于检索关联用户的基本账号信息,这些信息会在关联账号登录流程中向用户显示。
  • 您有 Android 应用。

工作原理

前提条件:用户之前已将其 Google 账号与您服务中的账号相关联。

  1. 您可以在一键式登录流程中选择显示已关联的账号。
  2. 系统会向用户显示一键式登录提示,其中包含使用关联的账号登录您的服务的选项。
  3. 如果用户选择继续使用关联的账号,Google 会向您的令牌端点发送请求,以保存授权代码。该请求包含您的服务发出的用户访问令牌和 Google 授权代码。
  4. 您可以将 Google 授权代码换取 Google ID 令牌,其中包含用户 Google 账号的相关信息。
  5. 流程完成后,您的应用还会收到一个 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 请求:

  • 验证 access_token 是否已授予由 client_id 标识的 Google。
  • 如果请求有效且身份验证码成功换成了 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 状态代码 正文 说明
400 {"error": "invalid_request"} 请求缺少参数,因此服务器无法继续处理该请求。如果请求包含不受支持的参数或重复参数,也可能会返回此错误
401 {"error": "invalid_request"} 客户端身份验证失败,例如请求包含无效的客户端 ID 或密钥
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 令牌

您需要将收到的授权代码换成 Google ID 令牌,其中包含用户 Google 账号的相关信息。

如需使用授权代码交换 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 令牌响应