google.accounts.oauth2
JavaScript 库可帮助您提示用户同意并获取访问令牌,以便处理用户数据。该库基于 OAuth 2.0 隐式授权流程,旨在让您能够使用 REST 和 CORS 直接调用 Google API,或者使用 适用于 JavaScript 的 Google API 客户端库(也称为 gapi.client
)轻松灵活地访问更复杂的 API。
在从浏览器访问受保护的用户数据之前,您网站上的用户会触发 Google 的基于 Web 的账号选择器、登录和意见征求流程,最后 Google 的 OAuth 服务器会向您的 Web 应用签发并返回访问令牌。
在基于令牌的授权模型中,无需在后端服务器上存储每位用户的刷新令牌。
建议您遵循此处所述的方法,而不是采用旧版适用于客户端 Web 应用的 OAuth 2.0 指南中介绍的技术。
设置
按照获取 Google API 客户端 ID 指南中所述的步骤查找或创建客户端 ID。接下来,将客户端库添加到您网站上将调用 Google API 的网页。最后,初始化令牌客户端。通常,这在客户端库的 onload
处理程序中完成。
初始化令牌客户端
调用 initTokenClient()
以使用 Web 应用的客户端 ID 初始化新的令牌客户端,您可以选择包含用户需要访问的一个或多个镜重的列表:
const client = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_GOOGLE_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
callback: (response) => {
...
},
});
触发 OAuth 2.0 令牌流程
使用 requestAccessToken()
方法触发令牌用户体验流程并获取访问令牌。Google 会提示用户:
- 选择其账号,
- 登录 Google 账号(如果尚未登录),
- 同意您的网站应用访问所请求的每个范围。
用户手势触发令牌流程:<button onclick="client.requestAccessToken();">Authorize me</button>
然后,Google 会向您的回调处理程序返回一个 TokenResponse
,其中包含访问令牌和用户已授予访问权限的范围列表,或者返回一个错误。
用户可能会关闭账号选择器或登录窗口,在这种情况下,系统不会调用您的回调函数。
如何处理用户意见征求
只有在仔细审核 Google 的 OAuth 2.0 政策后,才能实现应用的设计和用户体验。这些政策涵盖了使用多个镜重、何时以及如何处理用户意见征求等内容。
增量授权是一种政策和应用设计方法,用于仅在需要时(而不是预先一次性)使用镜重请求访问资源。用户可以批准或拒绝分享您的应用请求的各项资源,这称为精细权限。
在此过程中,Google 会提示用户同意,并单独列出每个请求的范围,用户选择要与您的应用共享的资源,最后,Google 会调用您的回调函数以返回访问令牌和用户批准的范围。然后,您的应用可以使用精细权限安全地处理可能出现的各种不同结果。
但也有例外情况。具有全网域授权的 Google Workspace 企业版应用或标记为受信任的应用会绕过精细权限同意页面。对于这些应用,用户不会看到精细权限意见征求界面。而是会收到所有请求的范围,或者一概不授予。
如需了解更多详情,请参阅如何处理精细权限。
增量授权
对于 Web 应用,以下两个概要场景演示了使用以下各项进行增量授权:
- 单页 Ajax 应用,通常使用
XMLHttpRequest
动态访问资源。 - 多个网页、资源按网页进行分隔和管理。
我们之所以提供这两种场景,是为了说明设计注意事项和方法,但并非旨在提供有关如何在应用中构建用户意见征求功能的全面建议。真实应用可能会使用这些方法的变体或组合。
Ajax
通过多次调用 requestAccessToken()
并使用 OverridableTokenClientConfig
对象的 scope
参数在需要时请求各个镜重范围(仅在必要时),为您的应用添加对增量授权的支持。在此示例中,只有在用户通过手势展开收起的内容部分后,系统才会请求资源并显示资源。
Ajax 应用 |
---|
在网页加载时初始化令牌客户端:
const client = google.accounts.oauth2.initTokenClient({ client_id: 'YOUR_GOOGLE_CLIENT_ID', callback: "onTokenResponse", }); 待阅读的文档显示近期的文档 client.requestAccessToken( overrideConfig = ({ scope = 'https://www.googleapis.com/auth/documents.readonly' }) ); 即将举办的活动显示日历信息 client.requestAccessToken( overrideConfig = ({ scope = 'https://www.googleapis.com/auth/calendar.readonly' }) ); 照片轮播界面显示照片 client.requestAccessToken( overrideConfig = ({ scope = 'https://www.googleapis.com/auth/photoslibrary.readonly' }) ); |
每次调用 requestAccessToken
都会触发用户同意时刻,您的应用将只能访问用户选择展开的部分所需的资源,从而限制通过用户选择进行资源共享。
多个网页
在设计增量授权时,多个网页仅用于请求加载网页所需的范围,从而降低复杂性,并无需进行多次调用即可征得用户同意并检索访问令牌。
多页面应用 | ||||||||
---|---|---|---|---|---|---|---|---|
|
每个网页都会在加载时调用 initTokenClient()
和 requestAccessToken()
来请求必要的范围并获取访问令牌。在这种情况下,各个网页用于按范围明确分隔用户功能和资源。在实际情况下,单个网页可能会请求多个相关的镜重。
精细权限
在所有情况下,精细权限的处理方式都是相同的;在 requestAccessToken()
调用您的回调函数并返回访问令牌后,请使用 hasGrantedAllScopes()
或 hasGrantedAnyScope()
检查用户是否已批准请求的范围。例如:
const client = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_GOOGLE_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly \
https://www.googleapis.com/auth/documents.readonly \
https://www.googleapis.com/auth/photoslibrary.readonly',
callback: (tokenResponse) => {
if (tokenResponse && tokenResponse.access_token) {
if (google.accounts.oauth2.hasGrantedAnyScope(tokenResponse,
'https://www.googleapis.com/auth/photoslibrary.readonly')) {
// Look at pictures
...
}
if (google.accounts.oauth2.hasGrantedAllScopes(tokenResponse,
'https://www.googleapis.com/auth/calendar.readonly',
'https://www.googleapis.com/auth/documents.readonly')) {
// Meeting planning and review documents
...
}
}
},
});
之前的会话或请求中之前接受的所有授权也会包含在响应中。系统会为每位用户和客户端 ID 维护一条用户意见征求记录,并在多次调用 initTokenClient()
或 requestAccessToken()
时保留该记录。默认情况下,只有在用户首次访问您的网站并请求新的范围时才需要征得用户同意,但系统可能会在每次加载网页时使用令牌客户端配置对象中的 prompt=consent
请求用户同意。
使用令牌
在令牌模型中,操作系统或浏览器不会存储访问令牌,而是会先在网页加载时获取新令牌,或者之后通过用户手势(例如按按钮)触发对 requestAccessToken()
的调用来获取新令牌。
将 REST 和 CORS 与 Google API 搭配使用
访问令牌可用于使用 REST 和 CORS 向 Google API 发出经过身份验证的请求。这样,用户就可以登录、授予同意,Google 可以签发访问令牌,您的网站也可以处理用户的数据。
在此示例中,使用 tokenRequest()
返回的访问令牌查看已登录用户的即将到来的日历活动:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
xhr.setRequestHeader('Authorization', 'Bearer ' + tokenResponse.access_token);
xhr.send();
如需了解详情,请参阅如何使用 CORS 访问 Google API。
下一部分将介绍如何轻松集成更复杂的 API。
使用 Google API JavaScript 库
令牌客户端可与 JavaScript 版 Google API 客户端库搭配使用。请参阅以下代码段。
const client = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_GOOGLE_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
callback: (tokenResponse) => {
if (tokenResponse && tokenResponse.access_token) {
gapi.client.setApiKey('YOUR_API_KEY');
gapi.client.load('calendar', 'v3', listUpcomingEvents);
}
},
});
function listUpcomingEvents() {
gapi.client.calendar.events.list(...);
}
令牌过期
访问令牌的生命周期很短,这是由设计决定的。如果访问令牌在用户会话结束之前过期,请通过用户触发的事件(例如按钮按下)调用 requestAccessToken()
来获取新令牌。
使用访问令牌撤消用户同意
调用 google.accounts.oauth2.revoke
方法可移除用户同意,并撤消向应用授予的所有权限范围对资源的访问权限。如需撤消此权限,您需要拥有有效的访问令牌:
google.accounts.oauth2.revoke('414a76cb127a7ece7ee4bf287602ca2b56f8fcbf7fcecc2cd4e0509268120bd7', done => {
console.log(done);
console.log(done.successful);
console.log(done.error);
console.log(done.error_description);
});