本文档介绍了如何实现 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,请按以下步骤操作:
- Open the API Library 在 Google API Console。
- If prompted, select a project, or create a new one.
- API Library 列出了所有可用的 API(按产品分组) 家庭和受欢迎程度。如果列表中没有显示您要启用的 API,请使用搜索功能 找到,或在产品系列中点击查看全部。
- 选择您要启用的 API,然后点击启用按钮。
- If prompted, enable billing.
- If prompted, read and accept the API's Terms of Service.
创建授权凭据
任何使用 OAuth 2.0 访问 Google API 的应用都必须具有授权凭据 来向 Google 的 OAuth 2.0 服务器标识应用以下步骤说明了如何 为项目创建凭据然后,您的应用就可以使用这些凭据访问 API 为该项目启用的功能
- Go to the Credentials page.
- 依次点击创建凭据 > OAuth 客户端 ID。
- 选择电视和受限输入设备应用类型。
- 为您的 OAuth 2.0 客户端命名,然后点击创建。
确定访问权限范围
范围让您的应用可以仅请求访问所需的资源,同时 让用户能够控制他们向您的应用授予的访问权限大小。因此, 请求的范围数量与可能性 征得用户同意。
在开始实现 OAuth 2.0 授权之前,我们建议您确定范围 您的应用需要获取访问权限的请求。
请参阅允许的范围列表,查看已安装的应用或设备。
获取 OAuth 2.0 访问令牌
即使您的应用在输入功能有限的设备上运行,用户也必须 访问具有更丰富输入功能的设备,以完成此授权流程。 该流程包含以下步骤:
- 您的应用向 Google 授权服务器发送请求以识别相关范围 您的应用将请求访问权限。
- 服务器会返回后续步骤中使用的一些信息,例如 设备代码和用户代码
- 您显示的信息供用户在单独的设备上输入,以便对您的 应用。
- 您的应用程序开始轮询 Google 的授权服务器以确定用户是否 已授权您的应用
- 用户切换到具有更丰富输入功能的设备,启动网络浏览器, 会转到第 3 步中显示的网址,然后输入第 3 步中显示的代码。通过 用户随后可以授予(或拒绝)对您的应用的访问权限。
- 对轮询请求的下一个响应包含应用需要授权的令牌 代表用户发出请求。(如果用户拒绝访问您的应用,则响应 不包含词元。)
下图演示了此过程:
![用户在装有浏览器的独立设备上登录](https://developers.google.cn/static/identity/protocols/images/oauth2/device/flow.png?authuser=5&hl=uk)
以下部分将详细介绍这些步骤。考虑到功能和运行时长的范围
设备可能具有的环境,本文档中显示的示例使用的是 curl
命令行实用程序。这些示例应该可以轻松移植到各种语言和运行时。
第 1 步:请求设备和用户代码
在此步骤中,您的设备会向 Google 的授权服务器发送 HTTP POST 请求,网址为
https://oauth2.googleapis.com/device/code
,用于标识您的应用
以及应用要代表用户访问的访问权限范围。
您应该从
发现文档(使用
device_authorization_endpoint
元数据值。包含以下 HTTP 请求
参数:
参数 | |
---|---|
client_id |
必需
应用的客户端 ID。您可以在 API Console Credentials page。 |
scope |
必需
答 空格分隔 范围列表,用于标识您的应用可以在 。这些值会告知 Google 向 用户。请参阅 已安装的应用或设备的允许的范围列表。 范围让您的应用可以仅请求访问所需的资源 同时让用户能够控制他们向您的网页授予 应用。因此,所请求的范围数量与 以及征得用户同意的可能性 |
示例
以下代码段显示了一个示例请求:
POST /device/code HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded client_id=client_id&scope=email%20profile
以下示例展示了用于发送同一请求的 curl
命令:
curl -d "client_id=client_id&scope=email%20profile" \ 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_url
和 user_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://
),请确保您的应用能够处理http
和https
变体。
- 显示
第 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 步中显示):
![输入代码以连接设备](https://developers.google.cn/static/identity/protocols/images/oauth2/device/user-code.png?authuser=5&hl=uk)
输入 user_code
并登录 Google(如果尚未登录)
用户会看到如下所示的同意屏幕:
![设备客户端的同意屏幕示例](https://developers.google.cn/static/identity/protocols/images/oauth2/device/approval.png?authuser=5&hl=uk)
第 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 客户端。例如,如果将
“ 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 的调用(例如,
调用 Drive Files API)。
您可以访问以下网址,试用所有 Google API 并查看其作用域: OAuth 2.0 Playground。
HTTP GET 示例
对
drive.files
端点(Drive Files API),同时使用 Authorization: Bearer
HTTP
可能如下所示。请注意,您需要指定自己的访问令牌:
GET /drive/v2/files HTTP/1.1 Host: www.googleapis.com Authorization: Bearer access_token
以下是使用 access_token
为经过身份验证的用户对同一 API 的调用
查询字符串参数:
GET https://www.googleapis.com/drive/v2/files?access_token=access_token
curl
示例
您可以使用 curl
命令行应用测试这些命令。这里有
使用 HTTP 标头选项的示例(首选):
curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files
或者,也可以使用查询字符串参数选项:
curl https://www.googleapis.com/drive/v2/files?access_token=access_token
刷新访问令牌
访问令牌会定期过期,并成为相关 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 Connect、 Google 登录
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
请参阅 使用“跨账号保护”页面保护用户账号 。