用于电视和有限输入设备应用程序的 OAuth 2.0

本文档介绍了如何实施 OAuth 2.0 授权以通过在电视、游戏机和打印机等设备上运行的应用程序访问 Google API。更具体地说,此流程专为无法访问浏览器或输入功能有限的设备而设计。

OAuth 2.0 允许用户与应用程序共享特定数据,同时将他们的用户名、密码和其他信息保密。例如,电视应用程序可以使用 OAuth 2.0 获得选择存储在 Google Drive 上的文件的权限。

由于使用此流程的应用程序分发到各个设备,因此假定应用程序无法保密。当用户在应用程序中或应用程序在后台运行时,他们可以访问 Google API。

备择方案

如果你正在写像Android,iOS设备的MacOS,Linux或Windows平台(包括通用Windows平台)应用程序,可以访问浏览器和全输入功能,使用移动和桌面应用程序的OAuth 2.0流。 (即使您的应用程序是没有图形界面的命令行工具,您也应该使用该流程。)

先决条件

为您的项目启用 API

调用谷歌API的应用程序需要能够在这些API API Console。

要为您的项目启用 API:

  1. Open the API Library 在 Google API Console。
  2. If prompted, select a project, or create a new one.
  3. 在 API Library 列出了所有可用的API,按产品系列和普及分组。如果要启用API不在列表中可见,用搜索找到它,或者点击查看全部的产品系列属于。
  4. 选择您要启用的API,然后点击启用按钮。
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

创建授权凭证

任何使用 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 授权之前,我们建议您确定您的应用需要访问权限的范围。

请参阅允许的范围进行安装的应用程序或设备列表中。

获取 OAuth 2.0 访问令牌

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

  1. 您的应用程序向 Google 的授权服务器发送请求,以标识您的应用程序将请求访问权限的范围。
  2. 服务器用后续步骤中使用的几条信息进行响应,例如设备代码和用户代码。
  3. 您显示用户可以在单独的设备上输入以授权您的应用程序的信息。
  4. 您的应用程序开始轮询 Google 的授权服务器以确定用户是否已授权您的应用程序。
  5. 用户切换到具有更丰富输入功能的设备,启动 Web 浏览器,导航到步骤 3 中显示的 URL 并输入也在步骤 3 中显示的代码。然后用户可以授予(或拒绝)对您的应用程序的访问权限。
  6. 对您的轮询请求的下一个响应包含您的应用代表用户授权请求所需的令牌。 (如果用户拒绝访问您的应用程序,则响应不包含令牌。)

下图说明了这个过程:

用户在具有浏览器的单独设备上登录

以下部分详细解释了这些步骤。给定的功能和运行时环境的是设备可具有的范围内,在本文档中示出的例子使用curl命令行实用程序。这些示例应该很容易移植到各种语言和运行时。

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

在这个步骤中,您的设备发送一个HTTP POST请求,谷歌的授权服务器,在https://oauth2.googleapis.com/device/code ,标识您的应用程序,以及访问的作用域,你的应用程序需要用户的访问代表。你应该检索来自该网址发现文档使用device_authorization_endpoint元数据值。包括以下 HTTP 请求参数:

参数
client_id必需的

您的应用程序的客户端 ID。你可以找到在这个值 API ConsoleCredentials 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_codeuser_code是有效的。如果此时用户没有完成授权流程,并且您的设备也没有轮询以检索有关用户决定的信息,则您可能需要从第 1 步重新开始此过程。
interval您的设备在轮询请求之间应等待的时间长度(以秒为单位)。例如,如果该值是5 ,您的设备将发送一个查询请求,每五秒钟谷歌的授权服务器。请参阅第3步的更多细节。
user_code一个区分大小写的值,用于向 Google 标识应用程序请求访问的范围。您的用户界面将指示用户在具有更丰富输入功能的单独设备上输入此值。当提示用户授予对您的应用程序的访问权限时,Google 然后使用该值显示正确的范围集。
verification_url一个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 步:显示用户代码

显示verification_urluser_code在步骤2中,以用户获得。这两个值都可以包含 US-ASCII 字符集中的任何可打印字符。您显示给用户的内容应指示用户导航到verification_url一个单独的设备上,并进入user_code

牢记以下规则来设计您的用户界面 (UI):

  • user_code
    • user_code必须显示在可处理15“W”大小字符的字段。换句话说,如果你能显示代码WWWWWWWWWWWWWWW正确,你的UI是有效的,我们建议测试方式,在使用该字符串值user_code在UI显示。
    • 所述user_code是大小写敏感的并且不应该以任何方式被修饰,如改变的情况下或插入其它格式化字符。
  • verification_url
    • 在这里你展示的空间verification_url必须足够宽,以处理URL字符串,它是长40个字符。
    • 你不应该修改verification_url以任何方式,除了有选择地删除显示方案。如果你打算剥离的方案(例如, https:// )从URL显示的原因,可以确保您的应用程序可以同时处理httphttps的变体。

第四步:轮询谷歌的授权服务器

由于用户将使用一个单独的装置以导航到verification_url和准许(或拒绝)的访问,请求装置不会自动当用户响应通知给访问请求。因此,发出请求的设备需要轮询 Google 的授权服务器,以确定用户何时响应了请求。

请求设备应继续发送轮询请求,直到它接收到指示用户已经响应了访问请求,或直到一个响应device_codeuser_code中获得步骤2已经过期。的interval在返回步骤2指定的时间量,以秒请求之间的等待。

端点投票网址是https://oauth2.googleapis.com/token 。轮询请求包含以下参数:

参数
client_id您的应用程序的客户端 ID。你可以找到在这个值 API ConsoleCredentials page
client_secret客户端秘密提供的client_id 。你可以找到在这个值 API ConsoleCredentials page
device_codedevice_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" \
         /token

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

下图显示了一个页面类似于用户看到,当他们浏览到verification_url您在显示第3步

通过输入代码连接设备

进入后user_code ,如果尚未登录,到谷歌日志,用户将看到一个同意画面像下面所示:

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

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

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

授予访问权限

如果该设备的用户授予访问权限(通过单击Allow同意屏幕上),那么响应包含一个访问令牌和刷新令牌。该令牌使您的设备访问谷歌的API代表用户的。 (该scope在响应确定哪些API设备可以访问的属性)。

在这种情况下,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"
}

其他错误

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

错误HTTP 状态码描述
invalid_client 401未找到 OAuth 客户端。例如,如果发生该错误client_id参数值是无效的。
invalid_grant 400code的参数值是无效的。
unsupported_grant_type 400grant_type参数值无效。

调用 Google API

在您的应用程序获得访问令牌后,如果已授予 API 所需的访问范围,您可以使用该令牌代表给定的用户帐户调用 Google API。要做到这一点,包括通过包括一个在请求令牌给API访问access_token查询参数或Authorization HTTP标头Bearer值。如果可能,最好使用 HTTP 标头,因为查询字符串往往在服务器日志中可见。在大多数情况下,你可以使用客户端库建立到谷歌的API您的来电(例如,当调用驱动器文件API )。

你可以尝试所有的谷歌API和查看他们的范围在的OAuth 2.0游乐场

HTTP GET 示例

在调用drive.files使用端点(驱动文件API) Authorization: Bearer HTTP标头看起来像下面这样。请注意,您需要指定自己的访问令牌:

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

下面是使用经过验证的用户相同的API调用access_token查询字符串参数:

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请求,谷歌的授权服务器( https://oauth2.googleapis.com/token ),它包括以下参数:

字段
client_id从所获得的客户机ID API Console
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 流程仅支持以下范围:

ID连接谷歌登录在

  • email
  • openid
  • profile

驱动器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