适用于 TV 应用和受限输入设备应用的 OAuth 2.0

本文档介绍了如何实现 OAuth 2.0 授权来访问 通过在电视、游戏机和 打印机进行打印。更具体地说,此流程适用于既没有设备访问权限的设备, 或输入功能有限。

OAuth 2.0 允许用户与应用共享特定数据,同时 用户名、密码和其他隐私信息 例如,电视应用可以使用 OAuth 2.0 来获得 选择存储在 Google 云端硬盘中的文件。

由于使用此流程的应用会被分发到各个设备,因此 应用无法保守 Secret。它们可以在用户 或当应用在后台运行时

替代方案

如果您要针对 Android、iOS、macOS、Linux 或 Windows 等平台编写应用 (包括通用 Windows 平台),可以访问浏览器和完整输入 请使用适用于移动设备的 OAuth 2.0 流程 和桌面应用。(即使您的应用是命令行应用,您也应该使用该流程 工具。)

如果您希望让用户使用其 Google 账号登录并使用 JWT ID 令牌,用于获取基本用户个人资料信息。 请参阅登录 支持电视和受限输入设备

前提条件

为您的项目启用 API

任何调用 Google API 的应用都需要在 API Console。

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

  1. Open the API Library 在 Google API Console。
  2. If prompted, select a project, or create a new one.
  3. 使用媒体库页面找到并启用 YouTube Data API。查找任何其他 以供您的应用使用并启用这些 API。

创建授权凭据

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

  1. Go to the Credentials page.
  2. 依次点击创建凭据 > OAuth 客户端 ID
  3. 选择电视和受限输入设备应用类型。
  4. 为您的 OAuth 2.0 客户端命名,然后点击创建

确定访问权限范围

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

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

YouTube Data API v3 使用以下范围:

Scopes
https://www.googleapis.com/auth/youtubeManage your YouTube account
https://www.googleapis.com/auth/youtube.channel-memberships.creatorSee a list of your current active channel members, their current level, and when they became a member
https://www.googleapis.com/auth/youtube.force-sslSee, edit, and permanently delete your YouTube videos, ratings, comments and captions
https://www.googleapis.com/auth/youtube.readonlyView your YouTube account
https://www.googleapis.com/auth/youtube.uploadManage your YouTube videos
https://www.googleapis.com/auth/youtubepartnerView and manage your assets and associated content on YouTube
https://www.googleapis.com/auth/youtubepartner-channel-auditView private information of your YouTube channel relevant during the audit process with a YouTube partner

请参阅允许的范围列表,查看已安装的应用或设备。

获取 OAuth 2.0 访问令牌

即使您的应用在输入功能有限的设备上运行,用户也必须 访问具有更丰富输入功能的设备,以完成此授权流程。 该流程包含以下步骤:

  1. 您的应用向 Google 授权服务器发送请求以识别相关范围 您的应用将请求访问权限。
  2. 服务器会返回后续步骤中使用的一些信息,例如 设备代码和用户代码
  3. 您显示的信息供用户在单独的设备上输入,以便对您的 应用。
  4. 您的应用程序开始轮询 Google 的授权服务器以确定用户是否 已授权您的应用
  5. 用户切换到具有更丰富输入功能的设备,启动网络浏览器, 会转到第 3 步中显示的网址,然后输入第 3 步中显示的代码。通过 用户随后可以授予(或拒绝)对您的应用的访问权限。
  6. 对轮询请求的下一个响应包含应用需要授权的令牌 代表用户发出请求。(如果用户拒绝访问您的应用,则响应 不包含词元。)

下图演示了此过程:

用户在装有浏览器的独立设备上登录

以下部分将详细介绍这些步骤。考虑到功能和运行时长的范围 设备可能具有的环境,本文档中显示的示例使用的是 curl 命令行实用程序。这些示例应该可以轻松移植到各种语言和运行时。

第 1 步:请求设备和用户代码

在此步骤中,您的设备会向 Google 的授权服务器发送 HTTP POST 请求,网址为 https://oauth2.googleapis.com/device/code,用于标识您的应用 以及应用要代表用户访问的访问权限范围。 您应该从 发现文档(使用 device_authorization_endpoint 元数据值。包含以下 HTTP 请求 参数:

参数
client_id 必需

应用的客户端 ID。您可以在 API Console Credentials page

scope 必需

答 空格分隔 范围列表,用于标识您的应用可以在 。这些值会告知 Google 向 用户。请参阅 已安装的应用或设备的允许的范围列表。

范围让您的应用可以仅请求访问所需的资源 同时让用户能够控制他们向您的网页授予 应用。因此,所请求的范围数量与 以及征得用户同意的可能性

YouTube Data API v3 使用以下范围:

Scopes
https://www.googleapis.com/auth/youtubeManage your YouTube account
https://www.googleapis.com/auth/youtube.channel-memberships.creatorSee a list of your current active channel members, their current level, and when they became a member
https://www.googleapis.com/auth/youtube.force-sslSee, edit, and permanently delete your YouTube videos, ratings, comments and captions
https://www.googleapis.com/auth/youtube.readonlyView your YouTube account
https://www.googleapis.com/auth/youtube.uploadManage your YouTube videos
https://www.googleapis.com/auth/youtubepartnerView and manage your assets and associated content on YouTube
https://www.googleapis.com/auth/youtubepartner-channel-auditView private information of your YouTube channel relevant during the audit process with a YouTube partner

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

示例

以下代码段显示了一个示例请求:

POST /device/code HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

client_id=client_id&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly

以下示例展示了用于发送同一请求的 curl 命令:

curl -d "client_id=client_id&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly" \
     https://oauth2.googleapis.com/device/code

第 2 步:处理授权服务器响应

授权服务器将返回以下响应之一:

成功响应

如果请求有效,响应将是包含以下内容的 JSON 对象 属性:

属性
device_code Google 唯一分配的值,用于标识运行请求的应用的设备 授权。用户将通过功能更丰富的其他设备向该设备授权 输入功能。例如,用户可能使用笔记本电脑或手机 电视运行的应用在本例中,device_code 标识电视。

此代码可让运行应用的设备安全地确定用户是否已授予 或拒绝访问

expires_in device_code 和 “user_code”有效。如果该用户在这段时间内没有完成 授权流程,并且您的设备不会轮询以检索有关 您可能需要从第 1 步重新开始此流程。
interval 您的设备在两次轮询请求之间应等待的时长(以秒为单位)。对于 例如,如果值为 5,您的设备应向 Google 的授权服务器每 5 秒发送一次。请参阅 第 3 步了解详情。
user_code 一个区分大小写的值,用于向 Google 标识应用所属的范围 请求访问权限。您的用户界面会指示用户在 具有更丰富的输入功能的独立设备。然后,Google 会使用该值 一组正确的范围。
verification_url 一个网址,用户必须在单独的设备上导航到该网址,才能输入 user_code,并授予或拒绝对您的应用的访问权限。您的界面 也会显示此值

以下代码段显示了一个示例响应:

{
  "device_code": "4/4-GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8",
  "user_code": "GQVQ-JKEC",
  "verification_url": "https://www.google.com/device",
  "expires_in": 1800,
  "interval": 5
}

“已超出配额”响应

如果您的设备代码请求已超出与您的客户端 ID 关联的配额,您将需要 收到包含以下错误的 403 响应:

{
  "error_code": "rate_limit_exceeded"
}

在这种情况下,请使用退避策略来降低请求速率。

第 3 步:显示用户代码

将第 2 步中获得的 verification_urluser_code 显示给 用户。这两个值可以包含 US-ASCII 字符集中的任何可打印字符。内容 应指示用户导航至 在另一台设备上输入 verification_url,然后输入 user_code

设计界面 (UI) 时,请牢记以下规则:

  • user_code
    • user_code 必须显示在可处理 15“W”值的字段中尺码 字符。也就是说,如果您可以将代码 WWWWWWWWWWWWWWW 正确,则您的 UI 是有效的,因此我们建议您在测试 user_code 会显示在您的界面中。
    • user_code 区分大小写,不应以任何方式进行修改,例如 更改大小写或插入其他格式字符。
  • verification_url
    • 显示verification_url的空间必须足够宽 处理长度为 40 个字符的网址字符串。
    • 您不应以任何方式修改 verification_url,除非是可以选择性修改 移除架构如果你打算去除协议 (例如 https://),请确保您的应用能够处理 httphttps 变体。

第 4 步:轮询 Google 的授权服务器

由于用户将使用单独的设备导航到 verification_url 并授予(或拒绝)访问权限,则当用户请求访问 Cookie 时,系统不会自动通知 对访问请求做出响应因此,请求设备需要轮询 Google 的 从而确定用户何时响应了请求

发出请求的设备应继续发送轮询请求,直到收到响应 表示用户已响应访问请求,或直到 device_code中获得了 [user_code] 第 2 步已过期。第 2 步中返回的 interval 指定了 请求之间的等待时间(以秒为单位)。

要轮询的端点的网址为 https://oauth2.googleapis.com/token。轮询请求 包含以下参数:

参数
client_id 应用的客户端 ID。您可以在 API Console Credentials page
client_secret 提供的 client_id 的客户端密钥。您可以在 API Console Credentials page
device_code 授权服务器在device_code 第 2 步
grant_type 将此值设置为 urn:ietf:params:oauth:grant-type:device_code

示例

以下代码段显示了一个示例请求:

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

client_id=client_id&
client_secret=client_secret&
device_code=device_code&
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code

以下示例展示了用于发送同一请求的 curl 命令:

curl -d "client_id=client_id&client_secret=client_secret& \
         device_code=device_code& \
         grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code" \
         -H "Content-Type: application/x-www-form-urlencoded" \
         https://oauth2.googleapis.com/token

第 5 步:用户响应访问权限请求

下图显示了一个页面,这个页面与用户导航到 verification_url(在第 3 步中显示):

输入代码以连接设备

输入 user_code 并登录 Google(如果尚未登录) 用户会看到如下所示的同意屏幕:

设备客户端的同意屏幕示例

第 6 步:处理对轮询请求的响应

Google 的授权服务器会使用以下某一项响应每个轮询请求: 响应:

已授予访问权限

如果用户向设备授予了访问权限(通过点击同意屏幕上的 Allow), 则响应包含访问令牌和刷新令牌。这些令牌可让您的设备 代表用户访问 Google API。(scope 属性决定了 设备可以访问的内容)。

在这种情况下,API 响应包含以下字段:

字段
access_token 您的应用为授权 Google API 请求而发送的令牌。
expires_in 访问令牌的剩余生命周期(以秒为单位)。
refresh_token 可用于获取新访问令牌的令牌。刷新令牌有效期至 用户撤消访问权限。 请注意,系统始终会为设备返回刷新令牌。
scope access_token 授予的访问权限范围,表示为 用空格分隔、区分大小写的字符串。
token_type 返回的令牌类型。目前,此字段的值始终设置为 Bearer

以下代码段显示了一个示例响应:

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "scope": "openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
  "token_type": "Bearer",
  "refresh_token": "1/xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}

访问令牌的生命周期有限。如果您的应用需要长时间访问某个 API 在一段时间内,它可以使用刷新令牌来获取新的访问权限 令牌。如果您的应用需要此类访问权限,则应为以下对象存储刷新令牌: 供稍后使用。

访问遭拒

如果用户拒绝授予对设备的访问权限,服务器响应将包含 403 HTTP 响应状态代码 (Forbidden)。响应包含 出现以下错误:

{
  "error": "access_denied",
  "error_description": "Forbidden"
}

待授权

如果用户尚未完成授权流程,则服务器会返回 428 HTTP 响应状态代码 (Precondition Required)。响应 包含以下错误:

{
  "error": "authorization_pending",
  "error_description": "Precondition Required"
}

轮询过于频繁

如果设备发送轮询请求的频率过高,服务器就会返回 403 HTTP 响应状态代码 (Forbidden)。响应包含以下内容 错误:

{
  "error": "slow_down",
  "error_description": "Forbidden"
}

其他错误

如果轮询请求缺少任何必需,则授权服务器也会返回错误。 或参数值不正确。这些请求通常具有 400 (Bad Request) 或 401 (Unauthorized) HTTP 响应状态 代码。这些错误包括:

错误 HTTP 状态代码 说明
admin_policy_enforced 400 由于 Google Workspace 管理员的政策。查看 Google Workspace 管理员帮助 文章控制哪些第三方和 内部应用会访问 Google Workspace 数据。 在明确授予您的 OAuth 访问权限之前,管理员可能会限制对范围的访问权限 客户端 ID。
invalid_client 401

找不到 OAuth 客户端。例如,如果将 “client_id”参数值无效。

OAuth 客户端类型不正确。请确保 应用程序类型 设置为电视和受限输入设备

invalid_grant 400 code”参数值无效、已被申领或无法被申领 已解析。
unsupported_grant_type 400 grant_type 参数值无效。
org_internal 403 请求中的 OAuth 客户端 ID 属于限制对 Google 账号进行访问的项目的一部分 特定的 Google Cloud Organization(Google Cloud 组织)。确认 用户类型 配置

调用 Google API

在您的应用获得访问令牌后,您就可以使用该令牌调用 Google 代表指定的 用户账号(如果已授予 API 所需的访问权限范围)。为此,请添加 通过添加 access_token 查询来获取对 API 的请求中的访问令牌 参数或 Authorization HTTP 标头 Bearer 值。如有可能, 最好使用 HTTP 标头,因为查询字符串通常显示在服务器日志中。大多数 可以使用客户端库来设置对 Google API 的调用(例如, 调用 YouTube Data API)。

请注意,YouTube Data API 仅支持 YouTube 服务账号 拥有和管理多个 YouTube 频道的内容所有者,例如 唱片公司和电影制片厂

您可以访问以下网址,试用所有 Google API 并查看其作用域: OAuth 2.0 Playground

HTTP GET 示例

youtube.channels 端点(YouTube Data API),并使用 Authorization: Bearer HTTP 可能如下所示。请注意,您需要指定自己的访问令牌:

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

刷新访问令牌

访问令牌会定期过期,并成为相关 API 请求的无效凭据。您 可以在不提示用户授予权限的情况下刷新访问令牌(包括在用户 不存在)。

为了刷新访问令牌,您的应用会发送 HTTPS POST 向 Google 的授权服务器 (https://oauth2.googleapis.com/token) 发送请求, 包含以下参数:

字段
client_id API Console获取的客户端 ID。
client_secret API Console获取的客户端密钥。
grant_type OAuth 2.0 规范中发现的问题, 此字段的值必须设置为 refresh_token
refresh_token 从授权代码交换返回的刷新令牌。

以下代码段显示了一个示例请求:

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

client_id=your_client_id&
client_secret=your_client_secret&
refresh_token=refresh_token&
grant_type=refresh_token

只要用户尚未撤消授予应用的访问权限,令牌服务器就会 会返回一个包含新访问令牌的 JSON 对象。以下代码段展示了一个示例 回答:

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "scope": "https://www.googleapis.com/auth/drive.metadata.readonly",
  "token_type": "Bearer"
}

请注意,发出的刷新令牌有数量限制;每个上限 客户/用户组合,以及另一个针对所有客户端的每位用户。您应该保存刷新令牌 ,只要它们保持有效状态,就可以继续使用。如果您的应用 请求过多刷新令牌,可能会受到这些限制,在这种情况下,较旧的刷新令牌 将停止运行。

撤消令牌

在某些情况下,用户可能希望撤消授予应用的访问权限。用户可以撤消访问权限 通过访问 账号设置。请参阅 删除 第三方网站和应用的“网站或应用访问权限”部分有权访问您账号的应用 支持文档。

应用也有可能以编程方式撤消授予其的访问权限。 如果用户退订、移除 或者应用所需的 API 资源发生了显著变化。也就是说, 移除流程的必要步骤可能包括 API 请求, 授予该应用的权限。

要以编程方式撤销令牌,您的应用会向 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 以及错误代码。

允许的范围

只有以下范围支持针对设备的 OAuth 2.0 流程:

OpenID ConnectGoogle 登录

  • email
  • openid
  • profile

Drive API

  • https://www.googleapis.com/auth/drive.appdata
  • https://www.googleapis.com/auth/drive.file

YouTube API

  • https://www.googleapis.com/auth/youtube
  • https://www.googleapis.com/auth/youtube.readonly

实施跨账号保护

您应采取的额外措施来保护用户的个账号实现了跨账号功能 利用 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

请参阅 使用“跨账号保护”页面保护用户账号