借助 Google 账号关联功能,Google 账号持有人可以快速、无缝、安全地连接到您的服务并与 Google 共享数据。
“关联的账号登录”功能可为已将其 Google 账号关联到您的服务的用户启用使用 Google 一键登录功能。这改善了用户体验,因为用户只需点击一下即可登录,无需重新输入用户名和密码。还可降低用户在您的服务中创建重复账号的几率。
要求
如需实现关联的账号登录功能,您必须满足以下要求:
- 您拥有支持 OAuth 2.0 授权代码流程的 Google 账号 OAuth 关联实现。您的 OAuth 实现必须包含以下端点:
<ph type="x-smartling-placeholder">
- </ph>
- 授权端点来处理授权请求。
- 令牌端点来处理对访问令牌和刷新令牌的请求。
- userinfo 端点 - 用于检索有关关联用户的基本账号信息,这些信息会在关联账号登录过程中向用户显示。
- 您有一个 Android 应用。
工作原理
前提条件 :用户之前已将其 Google 账号与其在您服务上的账号进行关联。
- 您可以在“一键登录”流程中选择显示关联的账号。
- 系统会向用户显示一键登录提示,并提供使用关联的账号登录您的服务的选项。
- 如果用户选择继续使用关联的账号,Google 会向您的令牌端点发送请求以保存授权代码。该请求包含您的服务颁发的用户访问令牌和 Google 授权代码。
- 您可以将 Google 授权代码换成包含用户 Google 账号相关信息的 Google ID 令牌。
- 该流程结束后,您的应用也会收到一个 ID 令牌,您要将此令牌与您的服务器收到的 ID 令牌中的用户标识符进行匹配,以便用户登录您的应用。
在 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 andhd
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.