借助 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 令牌响应
验证和解码 JWT 断言
您可以使用 适用于您所用语言的 JWT 解码库。使用 Google 的公钥,在 JWK 或 PEM 格式,用于验证 令牌的签名。
解码后,JWT 断言如以下示例所示:
{ "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 }
除了验证令牌的签名之外,还要验证断言的
颁发者(iss
字段)为 https://accounts.google.com
,
(aud
字段)是分配给您的客户端 ID,并且令牌未过期
(exp
字段)。
使用 email
、email_verified
和 hd
字段,您可以确定
Google 负责托管电子邮件地址,并对其具有权威性。如果 Google
权威性 - 用户当前被认定为合法账号所有者
您可以跳过密码或其他验证方法。否则,这些方法
可用于在关联之前验证账号。
Google 具有权威性的情形:
email
的后缀为@gmail.com
,这是一个 Gmail 账号。email_verified
为 true 且hd
已设置,这是 G Suite 账号。
用户无需使用 Gmail 或 G Suite 即可注册 Google 账号。时间
email
不包含 @gmail.com
后缀,且 hd
不存在 Google 不
建议使用权威凭据和密码或其他验证方法进行验证
用户。email_verified
可能为 true,因为 Google 最初验证了
创建 Google 账号后,该用户会获得第三方的所有权,
后,电子邮件账号可能已更改。