为 JavaScript Web 应用使用 OAuth 2.0

本文介绍了如何实现 OAuth 2.0 授权,以便从 JavaScript 网页应用访问 YouTube Analytics API 或 YouTube Reporting 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 身份服务的令牌模型,该模型基于 OAuth 2.0 隐式授权流程。

前提条件

为您的项目启用 API

任何调用 Google API 的应用都需要在 API Console中启用这些 API。

如需为您的项目启用该 API,请按以下步骤操作:

  1. Open the API Library (在 Google API Console中)。
  2. If prompted, select a project, or create a new one.
  3. 在“库”页面中查找并启用 YouTube Analytics API 和 YouTube Reporting API。许多检索 YouTube 分析工具数据的应用程序也与 YouTube 数据 API 连接。查找您的应用将使用的任何其他 API,并启用它们。

创建授权凭据

任何使用 OAuth 2.0 访问 Google API 的应用都必须具有授权凭据,用于向 Google 的 OAuth 2.0 服务器标识应用。以下步骤说明了如何为项目创建凭据。然后,您的应用就可以使用这些凭据访问已为该项目启用的 API。

  1. Go to the Credentials page.
  2. 依次点击创建凭据 > OAuth 客户端 ID
  3. 选择 Web 应用应用类型。
  4. 填写表单。 使用 JavaScript 发出已获授权的 Google API 请求的应用必须指定经授权的 JavaScript 来源。这些源标识可供您的应用从哪些网域向 OAuth 2.0 服务器发送请求。这些来源必须遵守 Google 的验证规则

确定访问权限范围

借助范围,您的应用可以仅请求访问所需的资源,同时还能让用户控制他们向您的应用授予的访问权限大小。因此,请求的范围数量与征得用户同意的可能性之间可能存在反向关系。

在开始实现 OAuth 2.0 授权之前,我们建议您先确定您的应用需要访问权限的范围。

YouTube Analytics API 使用以下范围:

范围
https://www.googleapis.com/auth/youtube管理您的YouTube帐户
https://www.googleapis.com/auth/youtube.readonly查看您的YouTube帐户
https://www.googleapis.com/auth/youtubepartner在YouTube上查看和管理您的资产和相关内容
https://www.googleapis.com/auth/yt-analytics-monetary.readonly查看您的YouTube内容的货币和非货币YouTube分析报告
https://www.googleapis.com/auth/yt-analytics.readonly查看有关您的YouTube内容的YouTube分析报告

YouTube Reporting API 使用以下范围:

范围
https://www.googleapis.com/auth/yt-analytics-monetary.readonly查看您的YouTube内容的货币和非货币YouTube分析报告
https://www.googleapis.com/auth/yt-analytics.readonly查看有关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 连接会被拒绝。

对于 Web 服务器应用,Google 授权服务器支持以下查询字符串参数:

参数
client_id 必需

您的应用的客户端 ID。您可以在 API Console Credentials page中找到此值。

redirect_uri 必需

确定在用户完成授权流程后 API 服务器会将用户重定向到何处。该值必须与您在客户端的 API Console Credentials page中配置的 OAuth 2.0 客户端的某个已授权重定向 URI 完全匹配。如果此值与提供的 client_id 经过授权的重定向 URI 不匹配,您会收到 redirect_uri_mismatch 错误。

请注意,httphttps 架构、大小写和尾随斜杠(“/”)必须全部匹配。

response_type 必需

JavaScript 应用需要将该参数的值设置为 token。此值指示 Google 授权服务器在完成授权流程后将用户重定向到的 URI (#) 的片段标识符中以 name=value 对的形式返回访问令牌。

scope 必需

用空格分隔的范围列表,用于标识您的应用可以代表用户访问的资源。这些值会告知 Google 向用户显示的同意屏幕。

范围可让您的应用仅请求访问所需的资源,同时还使用户能够控制他们向您的应用授予的访问权限大小。因此,请求的范围数量与征得用户同意的可能性之间存在反向关系。

YouTube Analytics API 使用以下范围:

范围
https://www.googleapis.com/auth/youtube管理您的YouTube帐户
https://www.googleapis.com/auth/youtube.readonly查看您的YouTube帐户
https://www.googleapis.com/auth/youtubepartner在YouTube上查看和管理您的资产和相关内容
https://www.googleapis.com/auth/yt-analytics-monetary.readonly查看您的YouTube内容的货币和非货币YouTube分析报告
https://www.googleapis.com/auth/yt-analytics.readonly查看有关您的YouTube内容的YouTube分析报告

YouTube Reporting API 使用以下范围:

范围
https://www.googleapis.com/auth/yt-analytics-monetary.readonly查看您的YouTube内容的货币和非货币YouTube分析报告
https://www.googleapis.com/auth/yt-analytics.readonly查看有关YouTube内容的YouTube分析报告

OAuth 2.0 API 范围文档提供了可用于访问 Google API 的范围的完整列表。

我们建议您的应用尽可能在上下文中请求访问授权范围。通过增量授权,您可以在用户执行相关操作时请求其访问用户数据,这有助于您更好地了解您的应用为何需要其所请求的访问权限。

state 建议

指定您的应用用来维护授权请求和授权服务器响应之间的状态的任何字符串值。当用户同意或拒绝应用的访问请求后,服务器会返回您在 redirect_uri 的网址片段标识符 (#) 中以 name=value 对形式发送的确切值。

您可以将此参数用于多种用途,例如将用户定向到应用中的正确资源、发送 Nonce,以及减少跨站请求伪造问题。由于您的 redirect_uri 可以被猜到,因此使用 state 值可以提高您的传入连接是身份验证请求结果的可能性。如果您生成随机字符串,或对 Cookie 或其他用于捕获客户端状态的值的哈希值进行编码,则可以验证响应,以额外确保请求和响应均来自同一浏览器,从而防范跨站请求伪造等攻击。如需查看如何创建和确认 state 令牌的示例,请参阅 OpenID Connect 文档。

include_granted_scopes 可选

允许应用使用增量授权在上下文中请求访问其他范围。如果您将此参数的值设为 true,并且授予了授权请求,则新的访问令牌还将涵盖用户之前授予应用访问权限的任何范围。如需查看示例,请参阅增量授权部分。

login_hint 可选

如果您的应用知道哪个用户正在尝试进行身份验证,它可以使用此参数向 Google Authentication 服务器提供提示。服务器会根据该提示,通过在登录表单中预填充电子邮件字段或选择适当的多登录会话来简化登录流程。

将该参数值设为电子邮件地址或 sub 标识符,该标识符相当于用户的 Google ID。

prompt 可选

向用户显示的提示列表,以空格分隔(区分大小写)。如果您未指定此参数,则系统只会在项目首次请求访问权限时提示用户。如需了解详情,请参阅 提示重新征得用户同意

可能的值包括:

none 不显示任何身份验证或同意屏幕。不得使用其他值指定。
consent 提示用户同意。
select_account 提示用户选择账号。

指向 Google 授权服务器的重定向示例

以下示例网址请求离线访问 (access_type=offline) 的范围,以允许访问检索用户的 YouTube 数据分析报告。它使用增量授权来确保新的访问令牌涵盖用户之前授予应用访问权限的任何范围。该网址还会为必需的 redirect_uriresponse_typeclient_id 参数以及 state 参数设置值。为了便于阅读,网址中包含换行符和空格。

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyt-analytics.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/yt-analytics.readonly',
                '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 账号无法向所请求的一个或多个范围授权。请参阅 Google Workspace 管理员帮助文章 控制哪些第三方应用和内部应用可以访问 Google Workspace 数据,详细了解管理员如何限制对所有范围或敏感范围和受限范围的访问权限,直到明确向您的 OAuth 客户端 ID 授予访问权限为止。

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 for iOS

当 iOS 或 macOS 应用在嵌入式用户代理中打开常规 Web 链接,并且用户从您的网站转到 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 的哈希代码段中返回,如下所示:

  • 访问令牌响应:

    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%2Fyt-analytics.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 Analytics API 时)。

请注意,YouTube Analytics API 不支持服务帐号流程。YouTube Reporting API 仅支持拥有并管理多个 YouTube 频道(例如唱片公司和电影制片厂)的 YouTube 内容所有者的服务账号。

您可以在 OAuth 2.0 Playground 中试用所有 Google API 并查看其范围。

HTTP GET 示例

使用 Authorization: Bearer HTTP 标头对 reports.query 端点 (YouTube Analytics API) 的调用可能如下所示。请注意,您需要指定自己的访问令牌:

GET /youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

以下是使用 access_token 查询字符串参数对已通过身份验证的用户的同一 API 的调用:

GET https://www.googleapis.com/youtube/analytics/v1/reports?access_token=access_token&ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views

curl 示例

您可以使用 curl 命令行应用测试这些命令。以下是使用 HTTP 标头选项(首选)的示例:

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views

或者,也可以使用查询字符串参数选项:

curl https://www.googleapis.com/youtube/analytics/v1/reports?access_token=access_token&ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views

JavaScript 示例代码

以下代码段演示了如何使用 CORS(跨域资源共享)向 Google API 发送请求。本示例未使用适用于 JavaScript 的 Google API 客户端库。但是,即使您未使用客户端库,该库文档中的 CORS 支持指南也可能有助于您更好地了解这些请求。

在此代码段中,access_token 变量表示您为了代表授权用户发出 API 请求而获取的令牌。完整示例演示了如何将该令牌存储在浏览器的本地存储空间中,并在发出 API 请求时检索该令牌。

var xhr = new XMLHttpRequest();
xhr.open('GET',
    'https://www.googleapis.com/youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views&' +
    '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 流程,此页面遵循以下步骤:

  1. 它会将用户定向到 Google 的 OAuth 2.0 服务器,该服务器会请求对 https://www.googleapis.com/auth/yt-analytics.readonly 范围的访问权限。
  2. 在授予(或拒绝)对一个或多个所请求范围的访问权限后,用户会被重定向到原始页面,该页面会从片段标识符字符串中解析访问令牌。
  3. 该页面使用访问令牌发出示例 API 请求。

    此 API 请求会调用 YouTube Analytics API 的 reports.query 方法,以获取授权用户的 YouTube 频道的观看次数。

  4. 如果请求成功执行,则浏览器的调试控制台中会记录 API 响应。

您可以通过 Google 帐号的权限页面撤消对该应用的访问权限。该应用将被列为 Google API 文档的 OAuth 2.0 演示版

如需在本地运行此代码,您需要为与您的授权凭据相对应的 YOUR_CLIENT_IDYOUR_REDIRECT_URI 变量设置值。YOUR_REDIRECT_URI 变量应设为提供网页的同一网址。该值必须与您在 API Console Credentials page中配置的 OAuth 2.0 客户端的某个已授权重定向 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';
  var fragmentString = location.hash.substring(1);

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0) {
    localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
    if (params['state'] && params['state'] == 'try_sample_request') {
      trySampleRequest();
    }
  }

  // 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/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views&' +
          '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() {
    // 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/yt-analytics.readonly',
                  'state': 'try_sample_request',
                  '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。本地主机 URI(包括 localhost IP 地址 URI)不受此规则限制。

主机

主机不能是原始 IP 地址。本地主机 IP 地址不受此规则限制。

网域
  • 主机 TLD(顶级域名)必须属于公共后缀列表
  • 主机域不能为 “googleusercontent.com”
  • 除非应用拥有该网域,否则 JavaScript 源不能包含 网址 Shortener 网域(例如 goo.gl)。
  • 用户信息

    JavaScript 源不能包含 userinfo 子组件。

    路径

    JavaScript 源不能包含路径组成部分。

    查询

    JavaScript 源不能包含查询组件。

    fragment

    JavaScript 来源不能包含 fragment 组件。

    字符 JavaScript 来源不能包含某些字符,包括:
    • 通配符 ('*')
    • 不可打印的 ASCII 字符
    • 百分号编码无效(任何百分号编码不符合以下格式的网址编码形式:百分号后跟两位十六进制数字)
    • 空字符(编码的 NULL 字符,例如%00%C0%80

    递增授权

    在 OAuth 2.0 协议中,您的应用会请求对访问由范围标识的资源的授权。在您需要时请求对资源进行授权被认为是一种最佳用户体验做法。为了实现这种做法,Google 的授权服务器支持增量授权。此功能允许您根据需要请求范围,如果用户授予新范围的权限,则会返回授权代码,您可以使用该代码来换取包含用户已授予项目的所有范围的令牌。

    例如,假设某个应用检索 YouTube 数据分析报告,其中一些报告是货币报告,需要访问其他报告不需要的额外范围。在这种情况下,在登录时,应用可能仅请求访问 https://www.googleapis.com/auth/yt-analytics.readonly 范围。但是,如果用户尝试检索货币报告,则应用也可以请求访问 https://www.googleapis.com/auth/yt-analytics-monetary.readonly 范围。

    以下规则适用于通过增量授权获取的访问令牌:

    • 令牌可用于访问与整合到新的组合授权中的任何范围相对应的资源。
    • 当您将刷新令牌用于合并授权以获取访问令牌时,访问令牌代表合并授权,并可用于响应中包含的任何 scope 值。
    • 组合授权包括用户授予 API 项目的所有范围,即使授权是从不同的客户端请求也是如此。例如,如果用户使用应用的桌面客户端向一个范围授予访问权限,然后通过移动客户端向同一应用授予另一个范围,则合并授权将同时涵盖这两个范围。
    • 如果您撤消代表合并授权的令牌,则代表关联用户对该授权范围的所有访问权限都会被同时撤消。

    以下代码示例展示了如何向现有访问令牌添加范围。此方法可让您的应用避免管理多个访问令牌。

    OAuth 2.0 端点

    在本例中,除了用户已向应用授予的任何其他访问权限之外,发起调用的应用还会请求检索用户的 YouTube 数据分析数据的权限。

    如需向现有访问令牌添加范围,请在向 Google OAuth 2.0 服务器发出的请求中添加 include_granted_scopes 参数。

    以下代码段演示了如何执行此操作。该代码段假设您已将访问令牌有效的范围存储在浏览器的本地存储空间中。(完整示例代码通过在浏览器的本地存储空间中设置 oauth2-test-params.scope 属性,存储访问令牌有效的范围列表。)

    该代码段会将访问令牌有效的范围与要用于特定查询的范围进行比较。如果访问令牌不涵盖该范围,则 OAuth 2.0 流程会开始。 此处,oauth2SignIn 函数与第 2 步中提供的函数相同(稍后将在完整示例中提供)。

    var SCOPE = 'https://www.googleapis.com/auth/yt-analytics.readonly';
    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();
    }