关联的帐号登录

借助 Google 账号关联功能,Google 账号持有人可以快速、无缝、安全地连接到您的服务并与 Google 共享数据。

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

要求

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

  • 您拥有支持 OAuth 2.0 授权代码流程的 Google 账号 OAuth 关联实现。您的 OAuth 实现必须包含以下端点: <ph type="x-smartling-placeholder">
      </ph>
    • 授权端点来处理授权请求。
    • 令牌端点来处理对访问令牌和刷新令牌的请求。
    • userinfo 端点 - 用于检索有关关联用户的基本账号信息,这些信息会在关联账号登录过程中向用户显示。
  • 您有一个 Android 应用。

工作原理

前提条件 :用户之前已将其 Google 账号与其在您服务上的账号进行关联。

  1. 您可以在“一键登录”流程中选择显示关联的账号。
  2. 系统会向用户显示一键登录提示,并提供使用关联的账号登录您的服务的选项。
  3. 如果用户选择继续使用关联的账号,Google 会向您的令牌端点发送请求以保存授权代码。该请求包含您的服务颁发的用户访问令牌和 Google 授权代码。
  4. 您可以将 Google 授权代码换成包含用户 Google 账号相关信息的 Google ID 令牌。
  5. 该流程结束后,您的应用也会收到一个 ID 令牌,您要将此令牌与您的服务器收到的 ID 令牌中的用户标识符进行匹配,以便用户登录您的应用。
<ph type="x-smartling-placeholder">
</ph> 关联的账号登录。 <ph type="x-smartling-placeholder">
</ph> 图 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 请求:

  • 验证是否已向 Google 授予 client_id 标识的access_token
  • 如果请求有效且身份验证代码已成功交换为 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 身份验证:不记名”响应标头中的身份验证质询

合作伙伴访问令牌无效。
403 {"error": "insufficient_permission"}

添加“WWW 身份验证:不记名”响应标头中的身份验证质询

合作伙伴访问令牌未包含执行双向 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 账号相关信息的 Google ID 令牌。

如要用授权代码换取 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 API 请求授权而发送的 Google 提供的访问令牌
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 令牌响应

Validate and decode the JWT assertion

You can validate and decode the JWT assertion by using a JWT-decoding library for your language. Use Google's public keys, available in JWK or PEM formats, to verify the token's signature.

When decoded, the JWT assertion looks like the following example:

{
  "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
}

In addition to verifying the token's signature, verify that the assertion's issuer (iss field) is https://accounts.google.com, that the audience (aud field) is your assigned client ID, and that the token has not expired (exp field).

Using the email, email_verified and hd fields you can determine if Google hosts and is authoritative for an email address. In cases where Google is authoritative the user is currently known to be the legitimate account owner and you may skip password or other challenges methods. Otherwise, these methods can be used to verify the account prior to linking.

Cases where Google is authoritative:

  • email has a @gmail.com suffix, this is a Gmail account.
  • email_verified is true and hd is set, this is a G Suite account.

Users may register for Google Accounts without using Gmail or G Suite. When email does not contain a @gmail.com suffix and hd is absent Google is not authoritative and password or other challenge methods are recommended to verify the user. email_verified can also be true as Google initially verified the user when the Google account was created, however ownership of the third party email account may have since changed.