本文档介绍了如何实现 OAuth 2.0 授权,以便从 JavaScript Web 应用访问 YouTube Data API。OAuth 2.0 允许用户与应用共享特定数据,同时保持其用户名、密码和其他信息的私密性。例如,应用可以使用 OAuth 2.0 来获得将视频上传到用户的 YouTube 频道的权限。
此 OAuth 2.0 流程称为隐式授权流程。它适用于仅在用户使用应用时访问 API 的应用。这些应用无法存储机密信息。
在此流程中,您的应用会打开一个 Google 网址,该网址使用查询参数来标识您的应用以及应用所需的 API 访问权限类型。您可以在当前浏览器窗口或弹出式窗口中打开网址。用户可以使用 Google 进行身份验证,并授予所请求的权限。 然后,Google 会将用户重定向回您的应用。重定向包含一个访问令牌,您的应用会对其进行验证,然后使用该令牌发出 API 请求。
Google API 客户端库和 Google Identity 服务
如果您使用 适用于 JavaScript 的 Google API 客户端库向 Google 发出已获授权的调用,则应使用 Google Identity 服务 JavaScript 库来处理 OAuth 2.0 流程。请参阅 Google Identity 服务的令牌模型,该模型基于 OAuth 2.0 隐式授予流程。
前提条件
为您的项目启用 API
任何调用 Google API 的应用都需要在 API Console中启用这些 API。
如需为您的项目启用该 API,请按以下步骤操作:
- Google API Console中的Open the API Library 。
- If prompted, select a project, or create a new one.
- 使用媒体库页面找到并启用 YouTube Data API。找到您的应用将使用的任何其他 API,并启用这些 API。
创建授权凭据
任何使用 OAuth 2.0 访问 Google API 的应用都必须具有授权凭据,以向 Google 的 OAuth 2.0 服务器表明应用的身份。以下步骤介绍了如何为项目创建凭据。然后,您的应用便可使用这些凭据访问您为该项目启用的 API。
- Go to the Credentials page.
- 依次点击创建凭据 > OAuth 客户端 ID。
- 选择 Web 应用应用类型。
- 填写表单。 使用 JavaScript 发出已获授权的 Google API 请求的应用必须指定已获授权的 JavaScript 源。源用于标识您的应用可以从哪些网域向 OAuth 2.0 服务器发送请求。这些来源必须遵守 Google 的验证规则。
确定访问权限范围
有了这一范围,您不但可以让应用仅请求访问所需的资源,而且还可以让用户控制其向您的应用授予的访问权限大小。因此,请求的范围数量与获得用户同意的可能性之间可能存在反比关系。
在开始实现 OAuth 2.0 授权之前,我们建议您确定应用需要访问权限的范围。
YouTube Data API v3 使用以下作用域:
瞄准镜 | |
---|---|
https://www.googleapis.com/auth/youtube | 管理您的 YouTube 帐号 |
https://www.googleapis.com/auth/youtube.channel-memberships.creator | 查看包含以下信息的列表:当前活跃的频道会员、其当前级别以及其成为会员的时间 |
https://www.googleapis.com/auth/youtube.force-ssl | 查看、修改以及永久删除您的 YouTube 视频、评分、评论和字幕 |
https://www.googleapis.com/auth/youtube.readonly | 查看您的 YouTube 帐号 |
https://www.googleapis.com/auth/youtube.upload | 管理您的 YouTube 视频 |
https://www.googleapis.com/auth/youtubepartner | 查看和管理您在 YouTube 上的资源和关联内容 |
https://www.googleapis.com/auth/youtubepartner-channel-audit | 查看您的 YouTube 频道中关于 YouTube 合作伙伴试演的隐私信息 |
OAuth 2.0 API 范围文档包含您可能用来访问 Google API 的完整范围列表。
获取 OAuth 2.0 访问令牌
以下步骤展示了您的应用如何与 Google 的 OAuth 2.0 服务器交互,以征得用户同意,从而代表用户执行 API 请求。您的应用必须先获得用户授权,然后才能执行需要用户授权的 Google API 请求。
第 1 步:重定向到 Google 的 OAuth 2.0 服务器
如需请求访问用户数据的权限,请将用户重定向到 Google 的 OAuth 2.0 服务器。
OAuth 2.0 端点
在 https://accounts.google.com/o/oauth2/v2/auth
生成一个网址,用于向 Google 的 OAuth 2.0 端点请求访问权限。此端点可通过 HTTPS 访问;系统会拒绝普通 HTTP 连接。
Google 授权服务器支持以下网站服务器应用查询字符串参数:
参数 | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
client_id |
必填
应用的客户端 ID。您可以在 API Console Credentials page中找到此值。 |
||||||||||||||||
redirect_uri |
必填
确定 API 服务器在用户完成授权流程后将用户重定向到何处。此值必须与 OAuth 2.0 客户端的已获授权重定向 URI 之一完全匹配,该 URI 是在客户端的 API Console
Credentials page中配置的。如果此值与提供的 请注意, |
||||||||||||||||
response_type |
必填
JavaScript 应用需要将该参数的值设置为 |
||||||||||||||||
scope |
必需
以空格分隔的范围列表,用于标识您的应用可以代表用户访问的资源。这些值用于填充 Google 向用户显示的意见征求页面。 有了这一范围,您不但可以让应用仅请求访问所需的资源,而且还可以让用户控制其向您的应用授予的访问权限大小。因此,请求的范围数量与获得用户同意的可能性之间存在反比关系。 YouTube Data API v3 使用以下作用域:
OAuth 2.0 API 范围文档提供了可用于访问 Google API 的范围的完整列表。 我们建议您的应用尽可能在用户实际使用过程中请求授权范围访问权限。通过渐进式授权请求在上下文中访问用户数据,您可以帮助用户更轻松地了解您的应用为何需要请求的访问权限。 |
||||||||||||||||
state |
推荐
指定您的应用用于维护授权请求与授权服务器响应之间的状态的任何字符串值。在用户同意或拒绝应用的访问请求后,服务器会返回您在 您可以将此参数用于多种用途,例如将用户定向到应用中的正确资源、发送 Nonce 以及减少跨网站请求伪造。由于您的 |
||||||||||||||||
include_granted_scopes |
可选
让应用能够使用增量授权来请求在上下文中访问其他作用域。如果将此参数的值设置为 |
||||||||||||||||
enable_granular_consent |
可选
默认为 当 Google 为应用启用精细权限时,此参数将不再有任何影响。 |
||||||||||||||||
login_hint |
可选
如果您的应用知道哪个用户正在尝试进行身份验证,则可以使用此参数向 Google 身份验证服务器提供提示。服务器使用提示来简化登录流程,方法是预填充登录表单中的电子邮件字段,或选择适当的多账号登录会话。 将参数值设置为电子邮件地址或 |
||||||||||||||||
prompt |
可选
一系列要向用户显示的提示(用空格分隔,区分大小写)。如果您未指定此参数,则系统仅会在您的项目首次请求访问权限时向用户显示提示。如需了解详情,请参阅 提示再次征求用户意见。 可能的值包括:
|
重定向到 Google 授权服务器的示例
以下示例网址请求对某个范围的离线访问权限 (access_type=offline
),该范围允许访问用户的 YouTube 账号。它使用增量授权来确保新访问令牌涵盖用户之前向应用授予访问权限的所有范围。该网址还会为必需的 redirect_uri
、response_type
和 client_id
参数以及 state
参数设置值。网址包含换行符和空格,以方便阅读。
https://accounts.google.com/o/oauth2/v2/auth?
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly&
include_granted_scopes=true&
state=state_parameter_passthrough_value&
redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
response_type=token&
client_id=client_id
创建请求网址后,将用户重定向到该网址。
JavaScript 示例代码
以下 JavaScript 代码段展示了如何在不使用适用于 JavaScript 的 Google API 客户端库的情况下,使用 JavaScript 启动授权流程。由于此 OAuth 2.0 端点不支持跨源资源共享 (CORS),因此该代码段会创建一个表单,用于打开对该端点的请求。
/* * Create form to request access token from Google's OAuth 2.0 server. */ function oauthSignIn() { // Google's OAuth 2.0 endpoint for requesting an access token var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth'; // Create <form> element to submit parameters to OAuth 2.0 endpoint. var form = document.createElement('form'); form.setAttribute('method', 'GET'); // Send as a GET request. form.setAttribute('action', oauth2Endpoint); // Parameters to pass to OAuth 2.0 endpoint. var params = {'client_id': 'YOUR_CLIENT_ID', 'redirect_uri': 'YOUR_REDIRECT_URI', 'response_type': 'token', 'scope': 'https://www.googleapis.com/auth/youtube.force-ssl', 'include_granted_scopes': 'true', 'state': 'pass-through value'}; // Add form parameters as hidden input values. for (var p in params) { var input = document.createElement('input'); input.setAttribute('type', 'hidden'); input.setAttribute('name', p); input.setAttribute('value', params[p]); form.appendChild(input); } // Add form to page and submit it to open the OAuth 2.0 endpoint. document.body.appendChild(form); form.submit(); }
第 2 步:Google 提示用户同意
在此步骤中,用户决定是否向您的应用授予所请求的访问权限。在此阶段,Google 会显示一个意见征求窗口,其中显示应用的名称,以及请求权限来使用用户授权凭据进行访问的 Google API 服务,以及要授予的访问范围摘要。然后,用户可以同意授予对应用请求的一个或多个范围的访问权限,也可以拒绝该请求。
在此阶段,您的应用无需执行任何操作,只需等待 Google 的 OAuth 2.0 服务器的响应,以确定是否已授予任何访问权限。下一步将介绍该响应。
错误
向 Google 的 OAuth 2.0 授权端点发出的请求可能会显示面向用户的错误消息,而不是预期的身份验证和授权流程。下面列出了常见的错误代码和建议的解决方法。
admin_policy_enforced
由于 Google Workspace 管理员的政策,Google 账号无法授权所请求的一个或多个镜重范围。如需详细了解管理员如何限制对所有镜重或敏感和受限镜重范围的访问,直至向您的 OAuth 客户端 ID 明确授予访问权限,请参阅 Google Workspace 管理中心帮助文章 控制哪些第三方应用和内部应用可以访问 Google Workspace 数据。
disallowed_useragent
授权端点显示在 Google 的 OAuth 2.0 政策所禁止的嵌入式用户代理中。
Android
Android 开发者在 android.webkit.WebView
中打开授权请求时可能会遇到此错误消息。
开发者应改为使用 Android 库,例如 Google 登录(适用于 Android)或 OpenID Foundation 的 AppAuth for Android。
当 Android 应用在嵌入式用户代理中打开常规网页链接,并且用户从您的网站导航到 Google 的 OAuth 2.0 授权端点时,Web 开发者可能会遇到此错误。开发者应允许在操作系统的默认链接处理程序(包括 Android App Links 处理程序或默认浏览器应用)中打开常规链接。我们也支持 Android 自定义标签页库。
iOS
iOS 和 macOS 开发者在 WKWebView
中打开授权请求时可能会遇到此错误。
开发者应改用 iOS 库,例如 Google 登录(iOS 版)或 OpenID Foundation 的 AppAuth(iOS 版)。
当 iOS 或 macOS 应用在嵌入式用户代理中打开常规网页链接,并且用户从您的网站导航到 Google 的 OAuth 2.0 授权端点时,Web 开发者可能会遇到此错误。开发者应允许通用链接在操作系统的默认链接处理程序中打开,其中包括通用链接处理程序或默认浏览器应用。SFSafariViewController
库也是受支持的选项。
org_internal
请求中的 OAuth 客户端 ID 属于一个项目,该项目会限制对特定 Google Cloud 组织中的 Google 账号的访问权限。如需详细了解此配置选项,请参阅“设置 OAuth 权限请求页面”帮助文章中的用户类型部分。
invalid_client
发出请求的来源未获授权访问此客户端。请参阅 origin_mismatch
。
invalid_grant
使用增量授权时,令牌可能已过期或已失效。 再次验证用户身份,并征得用户同意以获取新令牌。如果您仍然看到此错误消息,请确保您的应用已正确配置,且您在请求中使用了正确的令牌和参数。否则,用户账号可能已被删除或停用。
origin_mismatch
发起授权请求的 JavaScript 的架构、网域和/或端口可能与为 OAuth 客户端 ID 注册的授权 JavaScript 源 URI 不一致。请在 Google API Console Credentials page中查看已获授权的 JavaScript 来源。
redirect_uri_mismatch
授权请求中传递的 redirect_uri
与 OAuth 客户端 ID 的授权重定向 URI 不匹配。在 Google API Console Credentials page中查看已获授权的重定向 URI。
发起授权请求的 JavaScript 的架构、网域和/或端口可能与为 OAuth 客户端 ID 注册的已获授权的 JavaScript 来源 URI 不匹配。在 Google API Console Credentials page中查看已获授权的 JavaScript 来源。
redirect_uri
参数可能指的是已废弃且不再受支持的 OAuth 带外 (OOB) 流程。请参阅迁移指南,更新您的集成。
invalid_request
您提交的请求有问题。这可能由以下多种原因导致:
- 请求的格式不正确
- 请求缺少必需参数
- 请求使用的授权方法不受 Google 支持。验证您的 OAuth 集成是否使用了推荐的集成方法
第 3 步:处理 OAuth 2.0 服务器响应
OAuth 2.0 端点
OAuth 2.0 服务器向访问令牌请求中指定的 redirect_uri
发送响应。
如果用户批准了请求,则响应中会包含一个访问令牌。如果用户未批准请求,响应中会包含错误消息。访问令牌或错误消息会在重定向 URI 的哈希 fragment 中返回,如下所示:
访问令牌响应:
https://oauth2.example.com/callback#access_token=4/P7q7W91&token_type=Bearer&expires_in=3600
除了
access_token
参数之外,fragment 字符串还包含token_type
参数(始终设置为Bearer
)和expires_in
参数(用于指定令牌的生命周期,以秒为单位)。如果在访问令牌请求中指定了state
参数,则响应中也会包含其值。- 错误响应:
https://oauth2.example.com/callback#error=access_denied
OAuth 2.0 服务器响应示例
您可以点击以下示例网址来测试此流程,该网址会请求以只读权限查看您的 Google 云端硬盘中的文件:
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly& include_granted_scopes=true& state=state_parameter_passthrough_value& redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback& response_type=token& client_id=client_id
完成 OAuth 2.0 流程后,系统会将您重定向至 http://localhost/oauth2callback
。除非您的本地机器恰好在该地址上提供文件,否则该网址将会产生 404 NOT FOUND
错误。下一步将详细介绍在用户重定向回您的应用时 URI 中返回的信息。
调用 Google API
OAuth 2.0 端点
在您的应用获取访问令牌后,如果已授予某个 Google API 所需的访问权限范围,您就可以使用该令牌代表给定用户账号调用该 API。为此,请通过添加 access_token
查询参数或 Authorization
HTTP 标头 Bearer
值,在向 API 发出的请求中添加访问令牌。请尽可能使用 HTTP 标头,因为查询字符串通常会显示在服务器日志中。在大多数情况下,您可以使用客户端库设置对 Google API 的调用(例如,调用 YouTube Data API 时)。
请注意,YouTube Data API 仅支持拥有和管理多个 YouTube 频道的 YouTube 内容所有者的服务账号,例如唱片公司和电影制片厂。
您可以在 OAuth 2.0 Playground 中试用所有 Google API 并查看其范围。
HTTP GET 示例
使用 Authorization: Bearer
HTTP 标头来调用
youtube.channels
端点 (YouTube Data API) 可能如下所示。请注意,您需要指定自己的访问令牌:
GET /youtube/v3/channels?part=snippet&mine=true HTTP/1.1 Host: www.googleapis.com Authorization: Bearer access_token
以下是使用 access_token
查询字符串参数对已验证用户调用同一 API 的示例:
GET https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true
curl
示例
您可以使用 curl
命令行应用测试这些命令。下面是一个使用 HTTP 标头选项(首选)的示例:
curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true
或者,您也可以使用查询字符串参数选项:
curl https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true
JavaScript 示例代码
以下代码段演示了如何使用 CORS(跨源资源共享)向 Google API 发送请求。本示例不使用适用于 JavaScript 的 Google API 客户端库。 不过,即使您不使用客户端库,该库文档中的 CORS 支持指南也可以帮助您更好地了解这些请求。
在此代码段中,access_token
变量表示您为了代表授权用户发出 API 请求而获取的令牌。完整示例演示了如何将该令牌存储在浏览器的本地存储空间中,并在发出 API 请求时检索该令牌。
var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true&' + 'access_token=' + params['access_token']); xhr.onreadystatechange = function (e) { console.log(xhr.response); }; xhr.send(null);
完整示例
OAuth 2.0 端点
此代码示例演示了如何在不使用适用于 JavaScript 的 Google API 客户端库的情况下,在 JavaScript 中完成 OAuth 2.0 流程。该代码适用于用于显示用于试用 API 请求的按钮的 HTML 页面。如果您点击该按钮,代码会检查网页是否已在浏览器的本地存储空间中存储 API 访问令牌。如果是,则执行 API 请求。否则,它会启动 OAuth 2.0 流程。
对于 OAuth 2.0 流程,该页面会按照以下步骤操作:
- 它会将用户定向到 Google 的 OAuth 2.0 服务器,该服务器会请求对
https://www.googleapis.com/auth/youtube.force-ssl
范围的访问权限。 - 授予(或拒绝)对一个或多个请求的范围的访问权限后,系统会将用户重定向到原始页面,该页面会从 fragment 标识符字符串解析访问令牌。
该页面使用访问令牌来发出示例 API 请求。
此 API 请求会调用 YouTube Data API 的
channels.list
方法,以检索有关已获授权用户的 YouTube 频道的数据。- 如果请求成功执行,API 响应会记录在浏览器的调试控制台中。
您可以通过 Google 账号的权限页面撤消对该应用的访问权限。该应用会被列为适用于 Google API 文档的 OAuth 2.0 演示。
如需在本地运行此代码,您需要为 YOUR_CLIENT_ID
和 YOUR_REDIRECT_URI
变量设置与您的授权凭据对应的值。YOUR_REDIRECT_URI
变量应设置为与网页提供的网址相同。此值必须与 OAuth 2.0 客户端的已授权重定向 URI 之一完全匹配,您可以在 API Console Credentials page中配置这些 URI。如果此值与已授权的 URI 不匹配,您将收到 redirect_uri_mismatch
错误。您的项目还必须为此请求启用适当的 API。
<html><head></head><body> <script> var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE'; var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE'; // Parse query string to see if page request is coming from OAuth 2.0 server. var fragmentString = location.hash.substring(1); var params = {}; var regex = /([^&=]+)=([^&]*)/g, m; while (m = regex.exec(fragmentString)) { params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]); } if (Object.keys(params).length > 0 && params['state']) { if (params['state'] == localStorage.getItem('state')) { localStorage.setItem('oauth2-test-params', JSON.stringify(params) ); trySampleRequest(); } else { console.log('State mismatch. Possible CSRF attack'); } } // Function to generate a random state value function generateCryptoRandomState() { const randomValues = new Uint32Array(2); window.crypto.getRandomValues(randomValues); // Encode as UTF-8 const utf8Encoder = new TextEncoder(); const utf8Array = utf8Encoder.encode( String.fromCharCode.apply(null, randomValues) ); // Base64 encode the UTF-8 data return btoa(String.fromCharCode.apply(null, utf8Array)) .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); } // If there's an access token, try an API request. // Otherwise, start OAuth 2.0 flow. function trySampleRequest() { var params = JSON.parse(localStorage.getItem('oauth2-test-params')); if (params && params['access_token']) { var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true&' + 'access_token=' + params['access_token']); xhr.onreadystatechange = function (e) { if (xhr.readyState === 4 && xhr.status === 200) { console.log(xhr.response); } else if (xhr.readyState === 4 && xhr.status === 401) { // Token invalid, so prompt for user permission. oauth2SignIn(); } }; xhr.send(null); } else { oauth2SignIn(); } } /* * Create form to request access token from Google's OAuth 2.0 server. */ function oauth2SignIn() { // create random state value and store in local storage var state = generateCryptoRandomState(); localStorage.setItem('state', state); // Google's OAuth 2.0 endpoint for requesting an access token var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth'; // Create element to open OAuth 2.0 endpoint in new window. var form = document.createElement('form'); form.setAttribute('method', 'GET'); // Send as a GET request. form.setAttribute('action', oauth2Endpoint); // Parameters to pass to OAuth 2.0 endpoint. var params = {'client_id': YOUR_CLIENT_ID, 'redirect_uri': YOUR_REDIRECT_URI, 'scope': 'https://www.googleapis.com/auth/youtube.force-ssl', 'state': state, 'include_granted_scopes': 'true', 'response_type': 'token'}; // Add form parameters as hidden input values. for (var p in params) { var input = document.createElement('input'); input.setAttribute('type', 'hidden'); input.setAttribute('name', p); input.setAttribute('value', params[p]); form.appendChild(input); } // Add form to page and submit it to open the OAuth 2.0 endpoint. document.body.appendChild(form); form.submit(); } </script> <button onclick="trySampleRequest();">Try sample request</button> </body></html>
JavaScript 源验证规则
Google 会对 JavaScript 源应用以下验证规则,以帮助开发者确保其应用的安全性。您的 JavaScript 源必须遵循这些规则。 如需了解下文提到的网域、主机和架构的定义,请参阅 RFC 3986 第 3 节。
验证规则 | |
---|---|
架构 |
JavaScript 源必须使用 HTTPS 架构,而不是普通的 HTTP。localhost URI(包括 localhost IP 地址 URI)不受此规则的约束。 |
主机 |
主机不能是原始 IP 地址。本地主机 IP 地址不受此规则限制。 |
网域 |
“googleusercontent.com” 。goo.gl ),除非应用拥有相应网域。 |
用户信息 |
JavaScript 来源不能包含 userinfo 子组件。 |
路径 |
JavaScript 源不能包含路径组件。 |
查询 |
JavaScript 来源不能包含查询组件。 |
fragment |
JavaScript 来源不得包含 fragment 组件。 |
角色 |
JavaScript 来源不得包含某些字符,包括:
|
增量授权
在 OAuth 2.0 协议中,您的应用会请求访问资源的授权,这些资源由作用域标识。在需要资源时请求资源授权被视为最佳用户体验实践。为了实现这种做法,Google 的授权服务器支持增量授权。借助此功能,您可以根据需要请求权限范围,如果用户授予了新权限范围的权限,系统会返回一个授权代码,该代码可用于交换包含用户向项目授予的所有权限范围的令牌。
例如,假设某款应用可帮助用户查找有趣的当地活动。用户可以通过该应用观看有关赛事的视频、为视频评分,以及将视频添加到播放列表。用户还可以使用该应用将活动添加到其 Google 日历中。
在这种情况下,在用户登录时,应用可能不需要或不会请求访问任何范围。不过,如果用户尝试为视频评分、将视频添加到播放列表或执行其他 YouTube 操作,应用可以请求访问 https://www.googleapis.com/auth/youtube.force-ssl
范围。同样,如果用户尝试添加日历活动,应用也可以请求对 https://www.googleapis.com/auth/calendar
范围的访问权限。
以下规则适用于通过增量授权获取的访问令牌:
- 该令牌可用于访问与合并到新授权中的任何范围对应的资源。
- 当您使用组合授权的刷新令牌来获取访问令牌时,访问令牌代表组合授权,可用于响应中包含的任何
scope
值。 - 合并的授权包括用户向 API 项目授予的所有范围,即使授权是由不同的客户端请求也是如此。例如,如果用户使用应用的桌面客户端授予对一个范围的访问权限,然后通过移动客户端向同一应用授予另一个范围,则合并的授权将包括这两个范围。
- 如果您撤消代表组合授权的令牌,则系统会同时撤消代表关联用户对该授权的所有范围的访问权限。
以下代码示例展示了如何向现有访问令牌添加范围。通过这种方法,您的应用可以避免管理多个访问令牌。
OAuth 2.0 端点
在此示例中,除了用户已向应用授予的任何其他访问权限之外,调用应用还请求访问权限以检索用户的 YouTube Analytics 数据。
如需向现有访问令牌添加范围,请在对 Google OAuth 2.0 服务器的请求中添加 include_granted_scopes
参数。
以下代码段演示了如何执行此操作。该代码段假定您已在浏览器的本地存储空间中存储了访问令牌有效的范围。(完整示例代码会通过在浏览器的本地存储空间中设置 oauth2-test-params.scope
属性,存储访问令牌有效的范围列表。)
该代码段会将访问令牌有效的范围与您要针对特定查询使用的范围进行比较。如果访问令牌不涵盖该范围,系统会启动 OAuth 2.0 流程。
在这里,oauth2SignIn
函数与第 2 步中提供的函数相同(稍后将在完整示例中提供)。
var SCOPE = 'https://www.googleapis.com/auth/youtube.force-ssl'; var params = JSON.parse(localStorage.getItem('oauth2-test-params')); var current_scope_granted = false; if (params.hasOwnProperty('scope')) { var scopes = params['scope'].split(' '); for (var s = 0; s < scopes.length; s++) { if (SCOPE == scopes[s]) { current_scope_granted = true; } } } if (!current_scope_granted) { oauth2SignIn(); // This function is defined elsewhere in this document. } else { // Since you already have access, you can proceed with the API request. }
撤消令牌
在某些情况下,用户可能希望撤消向某个应用授予的访问权限。用户可以访问 账号设置撤消访问权限。如需了解详情,请参阅有权访问您账号的第三方网站和应用的“撤消网站或应用访问权限”部分。
应用还可以通过程序化方式撤消授予给它的访问权限。 在用户取消订阅、移除应用或应用所需的 API 资源发生重大变化的情况下,程序化撤消非常重要。换句话说,移除流程的一部分可以包含 API 请求,以确保移除之前授予应用的权限。
OAuth 2.0 端点
如需以编程方式撤消令牌,您的应用需要向 https://oauth2.googleapis.com/revoke
发出请求,并将令牌作为参数包含在内:
curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \ https://oauth2.googleapis.com/revoke?token={token}
该令牌可以是访问令牌或刷新令牌。如果令牌是访问令牌且具有相应的刷新令牌,则刷新令牌也会被撤消。
如果成功处理撤消,则响应的 HTTP 状态代码为 200
。对于错误情况,系统会返回 HTTP 状态代码 400
以及错误代码。
以下 JavaScript 代码段展示了如何在不使用适用于 JavaScript 的 Google API 客户端库的情况下通过 JavaScript 撤消令牌。由于用于撤消令牌的 Google OAuth 2.0 端点不支持跨源资源共享 (CORS),因此该代码会创建表单并将表单提交到端点,而不是使用 XMLHttpRequest()
方法发布请求。
function revokeAccess(accessToken) { // Google's OAuth 2.0 endpoint for revoking access tokens. var revokeTokenEndpoint = 'https://oauth2.googleapis.com/revoke'; // Create <form> element to use to POST data to the OAuth 2.0 endpoint. var form = document.createElement('form'); form.setAttribute('method', 'post'); form.setAttribute('action', revokeTokenEndpoint); // Add access token to the form so it is set as value of 'token' parameter. // This corresponds to the sample curl request, where the URL is: // https://oauth2.googleapis.com/revoke?token={token} var tokenField = document.createElement('input'); tokenField.setAttribute('type', 'hidden'); tokenField.setAttribute('name', 'token'); tokenField.setAttribute('value', accessToken); form.appendChild(tokenField); // Add form to page and submit it to actually revoke the token. document.body.appendChild(form); form.submit(); }
实施跨账号保护
为了保护用户的账号,您还应采取一项额外的措施,即利用 Google 的跨账号保护服务实现跨账号保护。借助此服务,您可以订阅安全事件通知,以便向您的应用提供有关用户账号重大更改的信息。然后,您可以根据自己决定如何响应事件,利用这些信息采取行动。
Google 跨账号保护服务向您的应用发送的事件类型示例包括:
-
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
-
https://schemas.openid.net/secevent/oauth/event-type/token-revoked
-
https://schemas.openid.net/secevent/risc/event-type/account-disabled
如需详细了解如何实现跨账号保护功能以及查看可发生事件的完整列表,请参阅 “使用跨账号保护功能保护用户账号”页面 。