ig281 发表于 前天 22:56

Google的OAuth 2.0 API竟有如此多用途,你真的了解它吗?

我们的 OAuth 2.0 API 具备身份验证和授权的双重功能。本指南详细阐述了我们遵循规范构建的 OAuth 2.0 身份验证机制,并已成功通过认证。针对访问 API 文档,OAuth 2.0 的使用方法同样适用。若您希望以互动形式深入了解该协议,我们推荐使用 OAuth 2.0 工具。若您打算在 Stack上寻求支持,务必在您的问题描述中包含“-oauth”这一标识。

若您需要在网站上设置“账号登录”功能,请采用我们的服务,该服务基于特定协议搭建了登录客户端库。该库支持特定格式的ID令牌。原生应用应通过相应API来完成“账号登录”的操作流程。

设置 OAuth 2.0

在您启用应用中的OAuth 2.0身份验证系统以供用户登录前,您需在相应平台内创建一个项目。此举旨在获取OAuth 2.0凭证,配置重定向URI,并且(如有需要)您可以自定义用户在意见征求界面中看到的品牌信息。此外,您还可以利用该平台创建服务账号、激活结算功能、设定过滤规则,以及执行其他相关任务。如需了解详情,请参阅 帮助。

获取 OAuth 2.0 凭据

您必须拥有OAuth 2.0凭证,这包括客户端ID和客户端密钥,以便对用户进行身份验证并获取访问API的权限。

设置重定向 URI

您在配置中指定的目标URI决定了应用将把响应发送至何地。

自定义用户同意屏幕

用户在使用OAuth 2.0身份验证的过程中,会遇到一个征求意见的界面,该界面会详细阐述用户需提供的信息和相关的使用条款。比如,在用户登录的过程中,系统可能会要求他们允许您的应用访问其电子邮件地址和基础账户信息。您可以通过添加特定参数来请求这些信息,而这个参数会被嵌入到您的应用中。您还可以使用镜重范围请求访问其他API。

在用户意见征询的界面中,亦会展示相关品牌资讯,诸如商品名称、标志以及主页链接。您有权对展示的品牌信息进行管理。

在意见征求对话框中,当请求内容涉及OAuth 2.0认证以及云端硬盘权限范围时,用户界面将呈现相应信息。需要注意的是,该通用对话框是由OAuth 2.0机制生成的,故其中不包含用于设置品牌信息的元素。

访问服务

我们向第三方提供了一系列库,这些库能够帮助处理用户身份验证及获取API访问权限的相关复杂细节。比如,这些库包括了适用于不同平台的服务和解决方案。

为确保执行上述操作的安全性,我们强烈建议您使用预先编写的库或服务。对用户进行准确的身份验证对于保障双方的安全至关重要。通常情况下,采用其他开发者验证通过的代码是一种理想的选择。如需获取更多信息,请查阅相关资料。

若您决定不采用该库,请参照本文件其他部分所述步骤进行,该部分内容详细阐述了使用这些库进行基本HTTP请求的具体流程。

对用户进行身份验证

身份验证过程中,必须获取并核实ID令牌。这构成了一个标准化的操作环节,主要目的是在互联网环境中实现身份声明的共享。

对用户身份进行核实并获取ID凭证的常见途径主要有两种,分别是“服务器”验证流程和“隐式”验证流程。其中,服务器验证流程使得应用的后端服务器得以对通过浏览器或移动设备登录的用户身份进行确认。而在客户端应用(通常运行于浏览器)需要直接访问API,而非依赖其后端服务器进行操作时,便会采用隐式验证流程。

本文档阐述了执行服务器流程以验证用户身份的方法。考虑到在客户端处理和使用令牌可能带来安全隐患,隐式流程相较于其他流程显得更为复杂。若您打算实施隐式流程,我们强烈推荐您选用我们的服务。

服务器流程

务必要确保,这样他们才能运用这些条款,并对用户身份进行核实。一旦用户试图通过账号进行登录,您应当:

1. 创建防伪造状态令牌

为确保用户安全,您需采取预防措施抵御请求伪造攻击。首先,需生成一个独一的会话标识符,该标识符将在您的应用与用户端设备间维持会话状态。随后,您可将此独一会话标识符与OAuth登录服务提供的认证结果相核对,以此确认请求是由用户发起,而非恶意攻击者。此类标识符通常被称作跨站请求伪造(CSRF)令牌。

采用高质量的随机数生成器,我们可以构建出约30个字符的字符串,这可以作为状态令牌的一个优选方案。另外,我们还可以通过在服务器端使用保密的密钥对会话状态变量的一部分进行签名,从而生成一个哈希值,这也是一种可行的状态令牌生成方法。

以下代码演示了如何生成唯一的会话令牌。

PHP

您必须下载 PHP 版API 客户端库才能使用此示例。

<p><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="PHP">    <span class="devsite-syntax-x">创建一个状态令牌,以防范请求伪造行为。</span>
<span class="devsite-syntax-x">将其存储于会话中,以便稍后进行验证。</span>
<span class="devsite-syntax-x">state 等于 将 128 比特随机字节 转换为 十六进制表示形式。</span>
<span class="devsite-syntax-x">应用程序的会话管理器将状态信息设置为$state。</span>
<span class="devsite-syntax-x">在HTML中设定客户端ID、令牌状态以及应用程序名称,同时,</span>
<span class="devsite-syntax-x">// serving it.</span>
<span class="devsite-syntax-x">将应用程序的模板引擎渲染出'index.html'页面,并传递相应的数组参数。</span>
<span class="devsite-syntax-x">    'CLIENT_ID' => CLIENT_ID,</span>
<span class="devsite-syntax-x">    'STATE' => $state,</span>
<span class="devsite-syntax-x">'应用程序名称' 等于 'APPLICATION_NAME'</span>
<span class="devsite-syntax-x">));</span></pre></p>
Java

为了运行这个示例,您需要先下载适用于 Java 的 API 客户端库。

<p><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Java">    <span class="devsite-syntax-c1">// Create a state token to prevent request forgery.</span>
<span class="devsite-syntax-c1">// Store it in the session for later validation.</span>
<span class="devsite-syntax-n">String</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-n">state</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">new</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-n">BigInteger</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">130</span><span class="devsite-syntax-p">,</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">new</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-n">SecureRandom</span><span class="devsite-syntax-p">()).</span><span class="devsite-syntax-na">toString</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">32</span><span class="devsite-syntax-p">);</span>
<span class="devsite-syntax-n">request</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-na">session</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-na">attribute</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"state"</span><span class="devsite-syntax-p">,</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-n">state</span><span class="devsite-syntax-p">);</span>
<span class="devsite-syntax-c1">将index.html文件内容读入内存,并设定客户端标识。</span>
<span class="devsite-syntax-c1">在向用户展示之前,需确保在HTML中正确填写了令牌状态以及应用程序名称。</span>
<span class="devsite-syntax-k">return</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">new</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-n">Scanner</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-k">new</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-n">File</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"index.html"</span><span class="devsite-syntax-p">),</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-s">"UTF-8"</span><span class="devsite-syntax-p">)</span>
<span class="devsite-syntax-w">    </span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-na">useDelimiter</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"\\A"</span><span class="devsite-syntax-p">).</span><span class="devsite-syntax-na">next</span><span class="devsite-syntax-p">()</span>
<span class="devsite-syntax-w">    </span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-na">replaceAll</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">将"[{"与"}]"之间的"CLIENT_ID"字样予以禁用。</span><span class="devsite-syntax-p">,</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-n">CLIENT_ID</span><span class="devsite-syntax-p">)</span>
<span class="devsite-syntax-w">    </span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-na">replaceAll</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"[{]{2}\\s*STATE\\s*[}]{2}"</span><span class="devsite-syntax-p">,</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-n">state</span><span class="devsite-syntax-p">)</span>
<span class="devsite-syntax-w">    </span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-na">replaceAll</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">将上述表达式拆分后,可以改写为:“\[\{\}\]空格*应用名称空格\[\}\]”。</span><span class="devsite-syntax-p">,</span>
<span class="devsite-syntax-w">    </span><span class="devsite-syntax-n">APPLICATION_NAME</span><span class="devsite-syntax-p">);</span></pre></p>
您必须下载版API 客户端库才能使用此示例。

<p><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python">    <span class="devsite-syntax-c1">创建一个状态令牌以防范请求伪造行为。</span>
<span class="devsite-syntax-c1">将其存储于会话中,以便稍后进行验证。</span>
<span class="devsite-syntax-n">state</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">hashlib</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">sha256</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">os</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">urandom</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">1024</span><span class="devsite-syntax-p">))</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">hexdigest</span><span class="devsite-syntax-p">()</span>
<span class="devsite-syntax-n">session</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s1">'state'</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">state</span>
<span class="devsite-syntax-c1">在HTML中设定客户端ID、令牌状态以及应用程序名称,同时,</span>
<span class="devsite-syntax-c1"># serving it.</span>
<span class="devsite-syntax-n">response</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">make_response</span><span class="devsite-syntax-p">(</span>
    <span class="devsite-syntax-n">render_template</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s1">'index.html'</span><span class="devsite-syntax-p">,</span>
                  <span class="devsite-syntax-n">CLIENT_ID</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-n">CLIENT_ID</span><span class="devsite-syntax-p">,</span>
                  <span class="devsite-syntax-n">STATE</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-n">state</span><span class="devsite-syntax-p">,</span>
                  <span class="devsite-syntax-n">APPLICATION_NAME</span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-n">APPLICATION_NAME</span><span class="devsite-syntax-p">))</span></pre></p>
2. 向发送身份验证请求

接下来的步骤是构建一个带有恰当 URI 参数的 HTTPS GET 请求。务必在整个操作过程中始终使用 HTTPS 协议,而不是 HTTP,因为系统将拒绝任何 HTTP 连接。您需要从检索基础 URI 中提取 nt 元数据值。以下讨论基于这样一个前提:基本 URI 为 。

对于基本请求,请指定以下参数:

请注意:上述内容仅展示了部分常用参数。若需查阅完整参数列表及更详尽的参数信息,请查阅相关资料。

以下提供了一个完整的身份验证统一资源标识符的实例,为了提高可读性,文本中加入了换行符以及空格。

<p><pre translate="no" dir="ltr" is-upgraded>   
禁止访问该链接:https://accounts.google.com/o/oauth2/v2/auth?
https://img2.baidu.com/it/u=2964654206,1376789754&fm=253&fmt=JPEG&app=138&f=JPEG?w=500&h=561

response_type=code&
client_id=<var translate="no">此ID:424911365001,属于谷歌身份验证服务,用于应用程序的认证。</var>&
scope=openid<var translate="no">%20email</var>&
redirect_uri=<var translate="no">请勿访问位于https://oauth2.example.com/code的链接。</var>&
state=<var translate="no">请勿修改,该字符串为安全令牌,其值为138r5719ru3e1,并且与网址https://oauth2-login-demo.example.com/myHome相关联。</var>&
login_hint=<var translate="no">jsmith@example.com</var>&
nonce=<var translate="no">0394852-3190485-2490358</var>&
hd=<var translate="no">example.com</var></pre></p>
若您的应用需索取用户新增的资料,亦或希冀查阅用户尚未授权的账户,务必先获得用户的明确许可。

3. 确认防伪造状态令牌

系统会将回复发送至您所设定的地址。所有回复内容都将包含在查询字符串中,呈现方式如下所示:

<p><pre translate="no" dir="ltr" is-upgraded>   
请勿访问该链接,其中包含用于获取授权码的参数,并且附带一个状态值。<var translate="no">安全令牌编号为138r5719ru3e1,访问链接为https://oa2cb.example.com/myHome。</var>&code=<var translate="no">禁止对特定内容进行篡改,确保信息的真实性,维护学术研究的严谨性。</var>限制范围为openid、电子邮件访问权限,以及允许通过https://www.googleapis.com/auth/userinfo.email接口获取用户信息。</pre></p>
在服务器端,您需核实所接收到的状态信息是否与您在本地所设置的会话标识相匹配。这种双向的验证机制,旨在验证请求确实源自用户,而非恶意脚本所发起。

以下代码演示了如何确认您在第 1 步中创建的会话令牌:

PHP

您必须下载 PHP 版API 客户端库才能使用此示例。

<p><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="PHP">    <span class="devsite-syntax-x">务必确保不存在请求伪造行为,并且用户</span>
<span class="devsite-syntax-x">正是这位用户,他本应向我们发送这一连接请求。</span>
<span class="devsite-syntax-x">若请求中获取的“状态”与应用会话中存储的“状态”不一致,{</span>
<span class="devsite-syntax-x">返回一个包含信息“无效的状态参数”的响应,状态码为401。</span>
<span class="devsite-syntax-x">}</span></pre></p>
Java

您必须下载 Java 版API 客户端库才能使用此示例。

<p><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Java">    <span class="devsite-syntax-c1">// Ensure that there is no request forgery going on, and that the user</span>
<span class="devsite-syntax-c1">// sending us this connect request is the user that was supposed to.</span>
<span class="devsite-syntax-k">if</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-o">!</span><span class="devsite-syntax-n">request</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-na">queryParams</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"state"</span><span class="devsite-syntax-p">).</span><span class="devsite-syntax-na">equals</span><span class="devsite-syntax-p">(</span>
<span class="devsite-syntax-w">    </span><span class="devsite-syntax-n">request</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-na">session</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-na">attribute</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"state"</span><span class="devsite-syntax-p">)))</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-n">response</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-na">status</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-mi">401</span><span class="devsite-syntax-p">);</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-k">return</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-n">GSON</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-na">toJson</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"Invalid state parameter."</span><span class="devsite-syntax-p">);</span>
<span class="devsite-syntax-p">}</span></pre></p>
您必须下载版API 客户端库才能使用此示例。

<p><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Python">    <span class="devsite-syntax-c1">务必核实该请求并非伪造,同时确保发送该请求的用户</span>
<span class="devsite-syntax-c1">此连接请求正是预期的用户。</span>
<span class="devsite-syntax-k">if</span> <span class="devsite-syntax-n">request</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">args</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">get</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s1">'state'</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-s1">''</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-o">!=</span> <span class="devsite-syntax-n">session</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s1">'state'</span><span class="devsite-syntax-p">]:</span>
<span class="devsite-syntax-n">response</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-n">make_response</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">json</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">dumps</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s1">'Invalid state parameter.'</span><span class="devsite-syntax-p">),</span> <span class="devsite-syntax-mi">401</span><span class="devsite-syntax-p">)</span>
<span class="devsite-syntax-n">response</span><span class="devsite-syntax-o">.</span><span class="devsite-syntax-n">headers</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-s1">'Content-Type'</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-o">=</span> <span class="devsite-syntax-s1">'application/json'</span>
<span class="devsite-syntax-k">return</span> <span class="devsite-syntax-n">response</span></pre></p>
4. 将 code 换成访问令牌和 ID 令牌

当请求中包含code参数时,意味着您的服务器可以凭借这一参数来获取访问令牌和ID令牌,这是一个用于一次性授权的代码。您需要通过发送HTTPS POST请求来完成这一交换过程。系统会将该POST请求转发至令牌端点,您需从请求的元数据值中提取出该端点的信息。在此讨论中,我们假设令牌端点为特定地址。在POST请求的正文里,必须包含以下参数:

字段

code

从返回的授权代码。

您从获取的客户端 ID,如中所述。

您从获取的客户端密钥,如中所述。

中指定的给定的已获授权的重定向 URI,如 中所述。

此字段的值必须为 ,。

实际请求可能如下所示:

<p><pre translate="no" dir="ltr" is-upgraded>   
POST /token HTTP/1.1
Host: oauth2.googleapis.com
内容类型:适用于URL编码的网页表单
code=<var translate="no">4/P7q7W91a-oMsCeLvIaQm6bTrgtp7</var>&
client_id=<var translate="no">your-client-id</var>&
client_secret=<var translate="no">your-client-secret</var>&
redirect_uri=<var translate="no">https%3A//oauth2.example.com/code</var>&
grant_type=authorization_code</pre></p>
对此请求的成功响应将在 JSON 数组中包含以下字段:

字段

可发送到API 的令牌。

访问令牌的剩余生命周期(以秒为单位)。

包含由数字签名的用户身份信息的 JWT。

scope

访问权限的授予范围,具体表现为由空格分隔、对大小写敏感的字符串序列。

标识返回的令牌类型。此时,此字段的值始终为 。

(选填)

https://img1.baidu.com/it/u=1819277194,356154724&fm=253&fmt=JPEG&app=138&f=JPEG?w=999&h=500

当参数设定为特定值时,该字段便会显现。若想获取详细信息,请查阅相关资料。

请注意,每个用户账号的令牌数量都有一定的限制,一旦超出这个限制,任何超出部分的身份验证请求都可能导致有效的刷新令牌被自动取消。如需进一步了解相关信息,请查阅相关资料。另外,从ID令牌中可以获取到用户的具体信息。

身份验证的ID凭证是JWT,也就是一种经过加密和签名的JSON格式对象。一般情况下,在使用之前,您需要先进行解码,接着才能进行操作。然而,鉴于您是通过无需中介的HTTPS通道直接与服务器进行交互,并且通过客户端密钥完成了身份验证,这使得您可以有充分的信心,确保接收到的令牌确实是由指定实体签发且真实有效的。若您的服务器向应用的其他部分发送了ID凭证,那么这些部分在利用该凭证之前,必须确保。

鉴于多数API库会将验证过程与编码解码操作及对JSON内容的解析整合在一起,所以在您尝试读取ID令牌中的声明时,仍有可能需要对令牌进行验证。

ID 令牌的载荷

ID令牌本质上是一个JSON对象,其中封装了一组名称与值相对应的数据。下面是一个经过格式优化的示例,便于大家阅读理解。

<p><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="JavaScript">    <span class="devsite-syntax-p">{</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-s2">"iss"</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"https://accounts.google.com"</span><span class="devsite-syntax-p">,</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-s2">"azp"</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">此账号的标识符为1234987819200@apps.googleusercontent.com。</span><span class="devsite-syntax-p">,</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-s2">"aud"</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"1234987819200.apps.googleusercontent.com"</span><span class="devsite-syntax-p">,</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-s2">"sub"</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">此编号为10769150350006150715113082367,不得进行任何修改。</span><span class="devsite-syntax-p">,</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-s2">"at_hash"</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"HK6E_P6Dh8Y93mRNtsDB1Q"</span><span class="devsite-syntax-p">,</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-s2">"hd"</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"example.com"</span><span class="devsite-syntax-p">,</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-s2">"email"</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"jsmith@example.com"</span><span class="devsite-syntax-p">,</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-s2">"email_verified"</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"true"</span><span class="devsite-syntax-p">,</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-s2">"iat"</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-mf">1353601026</span><span class="devsite-syntax-p">,</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-s2">"exp"</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-mf">1353604926</span><span class="devsite-syntax-p">,</span>
<span class="devsite-syntax-w"></span><span class="devsite-syntax-s2">"nonce"</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"0394852-3190485-2490358"</span>
<span class="devsite-syntax-p">}</span></pre></p>
请注意:在构建账号管理系统过程中,切勿将 ID 令牌中的电子邮件信息用作用户的独一标识。务必采用 sub 字段作为账号的唯一标识,即便用户更动了电子邮箱地址,此做法亦应坚持。

ID 令牌可能包含以下字段(称为声明):

领取提供说明

aud

始终

此ID令牌的适用对象是特定的。它应当是应用中OAuth 2.0客户端ID列表中的一员。

exp

始终

身份认证凭证的终止日期,在此日期及之后,不得再使用该凭证。该日期需以 Unix 时间格式(以整数秒为单位)来表示。

iat

始终

ID 令牌的发放时间。以 Unix 时间(整数秒数)表示。

iss

始终

对发行方的标识符进行响应。在ID令牌的使用上,应始终采用或 。

sub

始终

用户的标识符需在所有账号中保持独一无二,且不可被重复选用。账号可能在不同时间拥有多个电子邮箱,然而,sub 值始终固定不变。在应用过程中,应以 sub 作为用户唯一标识符的关键。其长度上限设定为255个可区分大小写的ASCII字符。

验证访问令牌的哈希值。此功能确保访问令牌与身份令牌之间的关联性。当服务器流程中通过值签发ID令牌时,该声明会自动包含。这一声明可以作为抵御跨网站请求伪造攻击的替代手段。然而,若您遵循既定操作流程,便无需对访问令牌进行验证。

azp

授权展示设备。仅在请求ID令牌的实体与目标ID令牌的用户群体不一致时,此声明方为必要。在混合应用场景中,此类情况可能发生,例如,当Web应用与移动应用采用不同的OAuth 2.0协议版本,却共享同一API项目时。

email

用户的电子信箱地址,仅在您的请求中明确要求提供电子邮件范围的情况下才会被提供。请注意,该声明的数值并非该账户的唯一标识,且其数值可能随时间推移而变动,因此您不应将此数值作为与用户档案关联的主要识别标志。此外,您也不应依赖电子邮件声明的域名来识别用户或Cloud组织的成员;在这种情况下,请改用hd声明。警示:切勿将电子邮件地址作为用户身份的唯一识别码,务必始终采用子账户字段。

用户邮件地址一旦经过核实,其验证结果即为真;若未通过核实,则判定为假。

用户的姓氏。存在声明时可以提供。

用户的名字。存在声明时可以提供。

hd

与用户关联的域或Cloud组织的域。只有在用户属于Cloud组织的情况下,才会提供此类域。若想将资源访问权限限定于特定域的成员,需勾选此声明。若无此声明,则表明该账户不属于托管域。

用户的语言区域可以通过 BCP 47 语言标记来体现,并在存在声明的情况下进行提供。

name

用户的全名(采用可显示的形式)。在以下情况下可以提供:

若存在相应名称的声明,您便能够利用这些声明来对应用中的用户信息进行更新。但需留意,我们无法确保该声明始终存在。

nonce

您的应用在身份验证过程中提交的随机数。请务必保证该随机数仅被使用一次,以有效抵御重放攻击的发生。

用户个人资料照片的网址。在以下情况下可以提供:

在提交相关声明的情况下,您有权利用这些声明来更新应用程序中的用户资料。然而,需留意的是,我们无法确保该声明将始终有效存在。

用户个人资料页面的网址。在以下情况下可以提供:

存在声明时,您可以使用这些声明更新应用的用户记录。请注意,我们无法保证此声明始终存在。

6. 对用户进行身份验证

获取用户信息于ID令牌之后,需对应用的用户数据库进行检索。若发现该用户已存在于数据库中,并且API的响应完全符合登录条件,则需启动该用户的应用会话。

若系统内未找到该用户资料,请引导用户进入注册新账号的流程。您可利用获取到的信息自动完成用户注册,亦或至少预先填写注册表单中的大部分必填项。除ID令牌提供的信息外,您还可以从我们的用户资料接口获取更多详细信息。

高级主题

本部分对OAuth 2.0 API进行了更为详尽的阐述,主要面向那些对身份验证与授权技术有较高需求的开发者群体。

访问其他API

OAuth 2.0 身份验证的一大优点在于,您的应用在验证用户身份时,还能获取代表用户操作其他API(如云端硬盘、日历或通讯录)的权限。为此,您需在发送给认证服务器的请求中包含所需的其他权限参数。比如,若要向认证请求中加入用户年龄段信息,您需传递指定电子邮件地址的范围参数。向用户展示相应的提示信息,您所获得的访问令牌能够使您有权访问那些您所请求并确认的访问权限范围内的所有API接口。

请注意:若您的应用需求项目众多,意见征询页面将展示多段文字。需求项目愈多,用户接受的可能性便会降低。因此,应用应仅请求必要的信息。请刷新令牌。

在申请使用API的访问权限时,您有权要求在特定时间段内获取刷新令牌。该令牌能够确保您的应用程序即便在用户未直接使用应用的情况下,也能持续地访问API。若您希望获取刷新令牌,请在相应的请求中设置特定参数。

注意事项:
页: [1]
查看完整版本: Google的OAuth 2.0 API竟有如此多用途,你真的了解它吗?