借助 Google Identity Services 库,用户可以请求授权 使用基于浏览器的弹出式窗口或重定向用户体验流程从 Google 获取代码。这个 启动安全的 OAuth 2.0 流程并生成用于调用 代表用户创建 Google API。
OAuth 2.0 授权代码流程摘要:
- 在浏览器中,通过点击按钮等手势,登录 Google 账号 所有者向 Google 申请授权代码。
- Google 会作出响应,并将唯一的授权代码发送给 或直接调用 授权代码端点。
- 您的后端平台托管授权代码端点并接收 代码。验证完成后,此代码将按用户获取和 通过向 Google 令牌端点发出的请求来刷新令牌。
- Google 验证授权代码,确认发出请求 发放访问令牌和刷新令牌,并返回 来请求获得令牌
- 您的登录端点接收访问和刷新令牌,安全地存储 刷新令牌以供日后使用
初始化代码客户端
google.accounts.oauth2.initCodeClient()
方法可初始化代码客户端。
弹出式窗口或重定向模式
您可以选择使用重定向或 弹出式窗口模式的用户流程。利用重定向模式,您可以托管 OAuth2 授权 端点,而 Google 会将用户代理重定向到此端点, 以网址参数的形式共享授权代码。对于弹出模式,您需要定义一个 回调处理程序,用于将授权代码发送到您的服务器。弹出模式 可以用来提供顺畅的用户体验, 离开您的网站。
如需为以下对象初始化客户端:
重定向用户体验流程,将
ux_mode
设置为redirect
,并将redirect_uri
添加到您的平台的授权代码端点。值 必须与 OAuth 2.0 的某一授权重定向 URI 完全匹配 您在 API 控制台中配置的客户端。此外,还必须符合我们的 重定向 URI 验证规则。弹出用户体验流程,将
ux_mode
设为popup
,并将callback
的值设置为 将授权代码发送到您的 平台。
防止 CSRF 攻击
为防止跨站请求伪造 (CSRF) 攻击,功能略有不同 重定向和弹出模式用户体验流程采用了各种技术用于重定向 模式下,系统会使用 OAuth 2.0 state 参数。请参阅 RFC6749 第 10.12 节 跨网站请求伪造 如需详细了解如何生成和验证 state 参数,使用“弹出式窗口”模式时 您在请求中添加自定义 HTTP 标头,然后在服务器上确认 它与预期的值和源相匹配。
选择 UX 模式即可查看显示身份验证代码和 CSRF 处理的代码段:
重定向模式
初始化客户端,以便 Google 将用户的浏览器重定向到您的 身份验证端点,以网址参数的形式共享身份验证代码。
const client = google.accounts.oauth2.initCodeClient({
client_id: 'YOUR_GOOGLE_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
ux_mode: 'redirect',
redirect_uri: "https://your.domain/code_callback_endpoint",
state: "YOUR_BINDING_VALUE"
});
弹出模式
初始化一个客户端,用户浏览器会从该客户端接收身份验证代码 Google 并将其发送到您的服务器。
const client = google.accounts.oauth2.initCodeClient({
client_id: 'YOUR_GOOGLE_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
ux_mode: 'popup',
callback: (response) => {
const xhr = new XMLHttpRequest();
xhr.open('POST', code_receiver_uri, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// Set custom header for CRSF
xhr.setRequestHeader('X-Requested-With', 'XmlHttpRequest');
xhr.onload = function() {
console.log('Auth code response: ' + xhr.responseText);
};
xhr.send('code=' + response.code);
},
});
触发 OAuth 2.0 代码流程
调用代码客户端的 requestCode()
方法以触发用户流:
<button onclick="client.requestCode();">Authorize with Google</button>
这需要用户登录 Google 账号并同意共享 然后再将授权代码返回至您的 重定向端点或回调处理程序。
授权代码处理
Google 会为每个用户生成一个唯一的授权代码,而该代码会 并在后端服务器上验证
对于弹出模式,由 callback
指定的处理程序,在用户的
会将授权代码中继到由您的平台托管的端点。
对于重定向模式,GET
请求将发送到由
redirect_url
,共享网址 code 参数中的授权代码。接收者
收到授权代码:
如果您没有现成的授权端点,请创建 实施,或者
更新您的现有端点以接受
GET
请求和网址 参数。以前,在PUT
请求中包含 有效负载
授权端点
您的授权代码端点必须使用以下网址查询处理 GET
请求:
字符串参数:
名称 | 值 |
---|---|
授权用户 | 用户登录身份验证请求 |
代码 | Google 生成的 OAuth2 授权代码 |
高清 | 用户账号的托管域 |
提示符 | 用户意见征求对话框 |
范围 | 要授权的一个或多个 OAuth2 范围的列表(以空格分隔) |
州 | CRSF 状态变量 |
使用网址参数向名为 auth-code 的端点的 GET
请求示例以及
由 example.com 托管:
Request URL: https://www.example.com/auth-code?state=42a7bd822fe32cc56&code=4/0AX4XfWiAvnXLqxlckFUVao8j0zvZUJ06AMgr-n0vSPotHWcn9p-zHCjqwr47KHS_vDvu8w&scope=email%20profile%20https://www.googleapis.com/auth/calendar.readonly%20https://www.googleapis.com/auth/photoslibrary.readonly%20https://www.googleapis.com/auth/contacts.readonly%20openid%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile&authuser=0&hd=example.com&prompt=consent
如果授权代码流由较早的 JavaScript 库启动,
或直接调用 Google OAuth 2.0 端点,系统会使用 POST
请求。
示例 POST
请求中包含作为有效负载的
HTTP 请求正文:
Request URL: https://www.example.com/auth-code
Request Payload: 4/0AX4XfWhll-BMV82wi4YwbrSaTPaRpUGpKqJ4zBxQldU\_70cnIdh-GJOBZlyHU3MNcz4qaw
验证请求
在您的服务器上执行以下操作,以避免 CSRF 攻击。
检查 state 参数的值(适用于重定向模式)。
确认 X-Requested-With: XmlHttpRequest
标头已设置为弹出模式。
然后,您应该继续从 Google 获取刷新令牌和访问令牌 前提是您首先成功验证了授权代码请求。
获取访问令牌和刷新令牌
在您的后端平台收到 Google 的授权代码后, 验证请求,使用授权代码从 进行 API 调用。
按照说明从第 5 步:交换授权代码 刷新和访问令牌中的为 Web 服务器使用 OAuth 2.0 应用指南。
管理令牌
您的平台会安全地存储刷新令牌。在以下情况下,系统会删除存储的刷新令牌:
用户账号被移除,或者用户已撤消同意
google.accounts.oauth2.revoke
或直接通过
https://myaccount.google.com/permissions.
(可选)您可以考虑使用 RISC 通过跨账号保护用户账号 保护。
通常,您的后端平台将使用访问令牌调用 Google API。如果
您的 Web 应用还会直接从用户浏览器调用 Google API,
必须实现一种方式,以便与 Web 应用共享访问令牌,
不在本指南的讨论范围内在采用此方法并使用
适用于 JavaScript 的 Google API 客户端库
使用 gapi.client.SetToken()
暂时在浏览器中存储访问令牌
内存,并启用该库来调用 Google API。