用于移动和桌面应用程序的 OAuth 2.0

本文档介绍了安装在手机、平板电脑和计算机等设备上的应用程序如何使用 Google 的 OAuth 2.0 端点来授权访问 Google API。

OAuth 2.0 允许用户与应用程序共享特定数据,同时将他们的用户名、密码和其他信息保密。例如,应用程序可以使用 OAuth 2.0 获得用户的许可,将文件存储在其 Google 云端硬盘中。

已安装的应用程序分发到各个设备,并且假定这些应用程序无法保密。当用户在应用程序中或应用程序在后台运行时,他们可以访问 Google API。

此授权流程类似于用于一个Web服务器应用程序。主要区别在于安装的应用程序必须打开系统浏览器并提供本地重定向 URI 来处理来自 Google 授权服务器的响应。

备择方案

对于移动应用,你可能更愿意使用谷歌登录在安卓iOS版。 Google Sign-in 客户端库处理身份验证和用户授权,它们可能比此处描述的低级协议更易于实现。

关于不支持的系统浏览器或设备上运行的应用程序具有有限的输入功能,如电视,游戏机,数码相机,或打印机,看到的OAuth 2.0用于电视和设备谷歌登录为设备

图书馆和样品

我们建议使用以下库和示例来帮助您实现本文档中描述的 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. 以下部分介绍了 Google 授权服务器支持的客户端类型和重定向方法。选择为您的应用程序推荐的客户端类型,命名您的 OAuth 客户端,并根据需要设置表单中的其他字段。

自定义 URI 方案(Android、iOS、UWP)

建议为 Android 应用、iOS 应用和通用 Windows 平台 (UWP) 应用使用自定义 URI 方案。

安卓
  1. 选择Android的应用程序类型。
  2. 输入 OAuth 客户端的名称。此名称显示在你的项目的 Credentials page 标识客户端。
  3. 输入您的 Android 应用程序的包名称。该值在所定义的package的属性<manifest>元件在应用清单文件。
  4. 输入应用分发的 SHA-1 签名证书指纹。
    • 如果应用程序使用的应用程序通过谷歌播放签约,从游戏控制台的应用程序签署页面复制SHA-1指纹。
    • 如果你管理自己的密钥存储和签名密钥,使用附带的Java keytool实用程序来打印证书信息在人类可读的格式。副本SHA1的价值Certificate fingerprints密钥工具输出的部分。请参阅验证您的客户在谷歌的API Android文档以获取更多信息。
  5. 点击创建
IOS
  1. 选择iOS的应用程序类型。
  2. 输入 OAuth 客户端的名称。此名称显示在你的项目的 Credentials page 标识客户端。
  3. 输入您的应用程序的包标识符。该包ID是价值CFBundleIdentifier在应用程序的信息属性列表资源文件(info.plist中)键。该值最常显示在 Xcode 项目编辑器的 General 窗格或 Signing & Capabilities 窗格中。束ID也显示在应用信息页面上的应用程序一般信息部分苹果的App Store Connect站点
  4. (可选的)

    如果应用程序在 Apple 的 App Store 中发布,请输入您的应用程序的 App Store ID。 Store ID 是包含在每个 Apple App Store URL 中的数字字符串。

    1. 打开苹果App Store应用的iOS或iPadOS设备上。
    2. 搜索您的应用。
    3. 选择共享按钮(方形和向上箭头符号)。
    4. 选择复制链接
    5. 将链接粘贴到文本编辑器中。 App Store ID 是 URL 的最后一部分。

      例如: https://apps.apple.com/app/google/id 284815942

  5. (可选的)

    输入您的团队 ID。见找到您的团队ID的苹果开发者帐户文档中获取更多信息。

  6. 点击创建
UWP
  1. 选择通用Windows平台的应用程序类型。
  2. 输入 OAuth 客户端的名称。此名称显示在你的项目的 Credentials page 标识客户端。
  3. 输入您的应用的 12 个字符的 Microsoft Store ID。你可以找到这个数值微软合作伙伴中心应用的身份在App管理部分页面。
  4. 点击创建

对于 UWP 应用,自定义 URI 方案不能超过 39 个字符。

环回 IP 地址(macOS、Linux、Windows 桌面)

要使用此 URL 接收授权代码,您的应用程序必须正在侦听本地 Web 服务器。这在许多平台上都是可能的,但不是所有平台。但是,如果您的平台支持它,则这是获取授权码的推荐机制。

当您的应用收到授权响应时,为了获得最佳可用性,它应该通过显示一个 HTML 页面来响应,指示用户关闭浏览器并返回到您的应用。

推荐用法macOS、Linux 和 Windows 桌面(但不是通用 Windows 平台)应用
表单值设置应用程序类型,以桌面应用

手动复制/粘贴

确定访问范围

范围使您的应用程序能够仅请求访问它需要的资源,同时还使用户能够控制他们授予您的应用程序的访问权限。因此,请求的范围数量与获得用户同意的可能性之间可能存在反比关系。

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

的OAuth 2.0 API范围文档包含范围,您可以使用访问谷歌的API的完整列表。

获取 OAuth 2.0 访问令牌

以下步骤显示您的应用程序如何与 Google 的 OAuth 2.0 服务器交互以获取用户的同意以代表用户执行 API 请求。您的应用程序必须先获得该同意,然后才能执行需要用户授权的 Google API 请求。

步骤 1:生成代码验证器和挑战

谷歌支持的交换代码证密钥(PKCE)协议,使安装的应用程序流更安全。为每个授权请求创建一个唯一的验证码,并将其转换后的值,称为“code_challenge”,发送到授权服务器以获取授权码。

创建代码验证器

code_verifier是使用未保留的字符[AZ]的高熵的加密随机串/ [AZ] / [0-9] / “ - ”/ “”。 / "_" / "~",最小长度为 43 个字符,最大长度为 128 个字符。

代码验证器应该有足够的熵来猜测值是不切实际的。

创建代码挑战

支持两种创建代码挑战的方法。

代码挑战生成方法
S256(推荐)代码挑战是代码验证器的 Base64URL(无填充)编码的 SHA256 哈希。
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
清楚的代码质询与上面生成的代码验证器的值相同。
code_challenge = code_verifier

第 2 步:向 Google 的 OAuth 2.0 服务器发送请求

为了获得用户授权,在发送给谷歌的授权服务器的请求https://accounts.google.com/o/oauth2/v2/auth 。此端点处理活动会话查找、对用户进行身份验证并获得用户同意。端点只能通过 SSL 访问,并且拒绝 HTTP(非 SSL)连接。

授权服务器支持已安装应用程序的以下查询字符串参数:

参数
client_id必需的

您的应用程序的客户端 ID。你可以找到在这个值 API ConsoleCredentials page

redirect_uri必需的

确定 Google 的授权服务器如何向您的应用发送响应。有可供安装的应用程序的几个重定向选项,你会设置你的授权证书在考虑一个特定的重定向方法。

该值必须完全匹配授权的重定向重定向的URI的OAuth 2.0用户端,您可以在您的客户机的配置的一个 API ConsoleCredentials page。如果此值不匹配授权的URI,你会得到一个redirect_uri_mismatch错误。

下表显示的适当redirect_uri为每个方法的参数值:

redirect_uri
自定义 URI 方案com.example.app : redirect_uri_path

或者

com.googleusercontent.apps.123 : redirect_uri_path
  • com.example.app在你的控制域的反向DNS表示法。自定义方案必须包含一个有效句点。
  • com.googleusercontent.apps.123是客户端ID的反向DNS符号。
  • redirect_uri_path是一个可选路径组件,诸如/oauth2redirect 。请注意,路径应以单斜杠开头,这与常规 HTTP URL 不同。
环回 IP 地址http://127.0.0.1: porthttp://[::1]: port

查询您的平台以获取相关的环回 IP 地址并在随机可用端口上启动 HTTP 侦听器。替代port与实际端口号,您的应用程序侦听。

手动复制/粘贴urn:ietf:wg:oauth:2.0:oob
程序化提取urn:ietf:wg:oauth:2.0:oob:auto
response_type必需的

确定 Google OAuth 2.0 端点是否返回授权代码。

设置参数值code安装的应用程序。

scope必需的

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

范围使您的应用程序能够仅请求访问它需要的资源,同时还使用户能够控制他们授予您的应用程序的访问权限。因此,请求的范围数量与获得用户同意的可能性之间存在反比关系。

code_challenge受到推崇的

指定的编码code_verifier将被用作授权码交换过程中的服务器端的挑战。请参阅创建代码的挑战上面的详细信息部分。

code_challenge_method受到推崇的

指定什么方法来编码code_verifier将授权码交换过程中使用。该参数必须与使用code_challenge上述参数。所述的值code_challenge_method默认为plain如果不存在,在包括该请求code_challenge 。此参数唯一支持的值是S256plain

state受到推崇的

指定您的应用程序用于维护授权请求和授权服务器响应之间的状态的任何字符串值。服务器返回您发送的精确值name=value对的URL片段标识符( #中的) redirect_uri用户同意后,或拒绝您的应用程序的访问请求。

您可以将此参数用于多种用途,例如将用户定向到应用程序中的正确资源、发送随机数以及减少跨站点请求伪造。由于您的redirect_uri可以猜到,使用state值可以增加你保证传入连接的认证请求的结果。如果您生成随机字符串或对 cookie 的哈希值或捕获客户端状态的其他值进行编码,则可以验证响应以额外确保请求和响应源自同一浏览器,从而提供针对跨站点等攻击的保护请求伪造。见ID连接文档中如何创建并确认一个例子state令牌。

login_hint可选的

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

设置参数值到电子邮件地址或sub标识符,这相当于用户的谷歌ID。

示例授权 URL

下面的选项卡显示了不同重定向 URI 选项的示例授权 URL。

的URL是除的值相同redirect_uri参数。的URL还包含所需response_typeclient_id参数以及可选的state参数。每个 URL 都包含换行符和空格以提高可读性。

自定义 URI 方案

https://accounts.google.com/o/oauth2/v2/auth?
 scope=email%20profile&
 response_type=code&
 state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foauth2.example.com%2Ftoken&
 redirect_uri=com.example.app%3A/oauth2redirect&
 client_id=client_id

环回 IP 地址

https://accounts.google.com/o/oauth2/v2/auth?
 scope=email%20profile&
 response_type=code&
 state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foauth2.example.com%2Ftoken&
 redirect_uri=http%3A//127.0.0.1%3A9004&
 client_id=client_id

复制粘贴

https://accounts.google.com/o/oauth2/v2/auth?
 scope=email%20profile&
 response_type=code&
 state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foauth2.example.com%2Ftoken&
 redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&
 client_id=client_id

程序化提取

https://accounts.google.com/o/oauth2/v2/auth?
 scope=email%20profile&
 response_type=code&
 state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foauth2.example.com%2Ftoken&
 redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob%3Aauto&
 client_id=client_id

第 3 步:Google 提示用户同意

在此步骤中,用户决定是否授予您的应用程序请求的访问权限。在此阶段,Google 会显示一个同意窗口,其中显示您的应用程序名称以及它请求使用用户授权凭据访问的 Google API 服务以及要授予的访问权限范围摘要。然后,用户可以同意授予对您的应用程序请求的一个或多个范围的访问权限或拒绝该请求。

您的应用程序在此阶段无需执行任何操作,因为它会等待来自 Google 的 OAuth 2.0 服务器的响应,指示是否授予任何访问权限。该响应将在以下步骤中进行解释。

错误

对 Google 的 OAuth 2.0 授权端点的请求可能会显示面向用户的错误消息,而不是预期的身份验证和授权流程。下面列出了常见的错误代码和建议的解决方法。

admin_policy_enforced

由于 Google Workspace 管理员的政策,Google 帐户无法授权一个或多个请求的范围。看到谷歌工作区管理员说明文章控制哪些第三方和内部应用程序访问谷歌工作区数据有关,直到访问被明确授予您的OAuth用户端ID管理员可以如何限制对所有范围或敏感和受限制的作用域的详细信息。

disallowed_useragent

授权端点是由谷歌的不允许的嵌入式用户代理内部显示的OAuth 2.0政策

安卓

在打开的授权请求时,Android开发可能会遇到此错误消息android.webkit.WebView 。开发者应该使用的Android库,如谷歌登录Android版或OpenID基金会的AppAuth未为Android

当 Android 应用程序在嵌入式用户代理中打开通用 Web 链接并且用户从您的站点导航到 Google 的 OAuth 2.0 授权端点时,Web 开发人员可能会遇到此错误。开发者应该允许一般链接到操作系统,其中包括默认链路处理器打开Android应用程序链接的处理程序或默认浏览器应用程序。在Android的自定义选项卡库也是支持的选项。

IOS

在打开的授权请求时,iOS和MacOS的开发商可能会遇到这个错误WKWebView 。开发者应该使用的iOS库,如谷歌登录在为iOS或OpenID基金会的AppAuth未适用于iOS

当 iOS 或 macOS 应用程序在嵌入式用户代理中打开通用 Web 链接并且用户从您的站点导航到 Google 的 OAuth 2.0 授权端点时,Web 开发人员可能会遇到此错误。开发者应该允许一般链接到操作系统,其中包括默认链路处理器打开通用链接处理程序或默认浏览器应用程序。该SFSafariViewController库也是支持的选项。

org_internal

在请求的OAuth用户端ID是项目限制在一个特定的访问谷歌帐户的一部分,谷歌云组织。有关此配置选项的详细信息,请参阅用户类型的设置您的OAuth同意画面帮助文章节。

redirect_uri_mismatch

redirect_uri在授权请求传递不匹配的OAuth用户端ID被授权的重定向URI。审查授权的重定向URI的 Google API Console Credentials page

传递的redirect_uri可能是客户端类型无效。

步骤 4:处理 OAuth 2.0 服务器响应

在其中应用程序接收到授权响应的方式取决于重定向URI方案,它使用。不管方案,响应要么包含一个授权代码( code )或一个错误( error )。例如, error=access_denied指示用户拒绝该请求。

如果用户授予对您的应用程序的访问权限,您可以按照下一步中的说明交换访问令牌和刷新令牌的授权代码。

第 5 步:交换刷新和访问令牌的授权代码

要对接入令牌交换授权代码,调用https://oauth2.googleapis.com/token端点并设置以下参数:

字段
client_id从所获得的客户机ID API ConsoleCredentials page
client_secret从获得的客户端秘密 API ConsoleCredentials page
code从初始请求返回的授权代码。
code_verifier验证你的代码中创建步骤1
grant_type如在OAuth 2.0规范中定义的,这个字段的值必须设置为authorization_code
redirect_uri一个在你的项目中列出的重定向URI的 API ConsoleCredentials page 对于给定的client_id

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

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

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob%3Aauto&
grant_type=authorization_code

Google 通过返回包含短期访问令牌和刷新令牌的 JSON 对象来响应此请求。

响应包含以下字段:

字段
access_token您的应用程序发送以授权 Google API 请求的令牌。
expires_in访问令牌的剩余生命周期(以秒为单位)。
id_token注意:如果您的请求包含一个身份范围,如该属性才会返回openidprofile ,或email 。该值是一个 JSON Web 令牌 (JWT),其中包含有关用户的数字签名身份信息。
refresh_token可用于获取新访问令牌的令牌。刷新令牌在用户撤销访问之前一直有效。请注意,始终为已安装的应用程序返回刷新令牌。
scope访问的范围授出access_token表示为空格分隔,区分大小写字符串列表。
token_type返回的令牌类型。在这个时候,这个字段的值总是被设置为Bearer

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

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

调用 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。 (该client_secret不适用于从注册为Android,iOS设备或Chrome应用程序客户端的请求。)
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与错误代码一起返回。

进一步阅读

在IETF最佳当前做法的OAuth 2.0本机应用程序建立了许多这里记录的最佳实践。