Tian Jiale's Blog

RFC6749 | OAuth 2.0 授权框架 中文版

前言

摘要

OAuth2.0 授权框架允许第三方应用获取对 HTTP 服务的有限的访问权限,既可以以资源所有者名义在资源所有者和 HTTP 服务之间进行允许的交互,也可以允许第三方应用以自己的名义进行访问。本规范取代并淘汰 RFC 5849 中描述的 OAuth 1.0 协议。

本备忘录状态

这是一个互联网标准化过程文档。

本文档是互联网工程任务组(IETF)的作品。它代表了 IETF 社区的一致看法。它已接受公开审阅并由互联网工程指导小组(IESG)批准公布。有关互联网标准的进一步信息可在 RFC 5741 的第 2 节找到。

有关本文档的当前状态、勘误表以及如何对它提供反馈可参见 http://www.rfc-editor.org/info/rfc6749

版权声明

IETF 信托及标识为本文档的作者的个人版权所有(c)2012。保留所有权利。

本文档受 BCP78 和 IETF 信托有关 IETF 文档的法律条款 (http://trustee.ietf.org/license-info)的约束,自本文档发布之日起生效。请仔细查阅这些文件,因为它们描述了与本文档有关的权利和限制。从本文档中提取的代码片段必须按信托法律条款 4.e 节所述包括简化 BSD 许可证文本;并且按简化 BSD 许可证中所述不附带质量保证。

目录

[toc]

1. 简介

在传统的客户端-服务器身份验证模式中,客户端请求服务器上限制访问的资源(受保护资源)时,需要使用资源所有者的凭据在服务器上进行身份验证。资源所有者为了给第三方应用提供受限资源的访问,需要与第三方共享它的凭据。 这造成一些问题和局限:

  • 需要第三方应用存储资源所有者的凭据,以供将来使用,通常是明文密码。

  • 需要服务器支持密码身份认证,尽管密码认证天生就有安全缺陷。

  • 第三方应用获得的资源所有者的受保护资源的访问权限过于宽泛,从而导致资源所有者失去对资源使用时限或使用范围的控制。

  • 资源所有者不能在不撤销对所有第三方的访问权限的情况下撤销对单个第三方的访问权限,而且必须通过更改第三方的密码来这样做。

  • 与任何第三方应用的让步导致对终端用户的密码及该密码所保护的所有数据的让步。

OAuth 通过引入授权层以及分离客户端角色和资源所有者角色来解决这些问题。在 OAuth 中,客户端在请求受资源所有者控制并托管在资源服务器上的资源的访问权限时,将被颁发一组不同于资源所有者所拥有凭据的凭据。

客户端获得一个访问令牌(一个代表特定作用域、生命期以及其他访问属性的字符串),用以代替使用资源所有者的凭据来访问受保护资源。访问令牌由授权服务器在资源所有者认可的情况下颁发给第三方客户端。客户端使用访问令牌访问托管在资源服务器的受保护资源。

例如,终端用户(资源所有者)可以授权一个打印服务(客户端)访问她存储在图片分享服务(资源服务器)上的受保护图片,而无需与打印服务分享自己的用户名和密码。反之,她直接与图片分享服务信任的服务器(授权服务器)进行身份验证,该服务器颁发给打印服务具体委托凭据(访问令牌)。

本规范是为 HTTP([RFC2616])协议定制。在任何非 HTTP 协议上使用 OAuth 不在本规范的范围之内。

OAuth 1.0 协议([RFC5849])作为一个指导性文档发布,是一个小社区的工作成果。本标准化规范在 OAuth 1.0 的部署经验之上构建,也包括其他使用案例以及从更广泛的 IETF 社区收集到的可扩展性需求。OAuth 2.0 协议不向后兼容 OAuth 1.0。这两个版本可以在网络上共存,实现者可以选择同时支持他们。然而,本规范的用意是新的实现支持按本文档指定的 Auth 2.0,OAuth 1.0 仅用于支持现有的部署。OAuth 2.0 协议与 OAuth 1.0 协议实现细节没有太多关联。熟悉 OAuth 1.0 的实现者应该学习本文档,而不对有关 OAuth 2.0 的结构和细节做任何假设。

1.1. 角色

OAuth 定义了四种角色:

  • 资源所有者

    能够授予对受保护资源访问权限的实体。当资源所有者是一个人时,它被称为终端用户。

  • 资源服务器

    托管受保护资源的服务器,能够接收和响应使用访问令牌对受保护资源的请求。

  • 客户端

    代表资源所有者并经其授权请求受保护资源的应用程序。术语"客户端"并不意味着任何特定的实现特征(例如,应用程序是否在服务器、桌面或其他设备上执行)。

  • 授权服务器

    在成功验证资源所有者且获得授权后颁发访问令牌给客户端的服务器。

授权服务器和资源服务器之间的交互超出了本规范的范围。授权服务器和资源服务器可以是同一台服务器,也可以是分离的个体。一个授权服务器可以颁发多个资源服务器接受的访问令牌。

1.2. 协议流程

   +--------+                               +---------------+
   |        |--(A)- Authorization Request ->|   Resource    |
   |        |                               |     Owner     |
   |        |<-(B)-- Authorization Grant ---|               |
   |        |                               +---------------+
   |        |
   |        |                               +---------------+
   |        |--(C)-- Authorization Grant -->| Authorization |
   | Client |                               |     Server    |
   |        |<-(D)----- Access Token -------|               |
   |        |                               +---------------+
   |        |
   |        |                               +---------------+
   |        |--(E)----- Access Token ------>|    Resource   |
   |        |                               |     Server    |
   |        |<-(F)--- Protected Resource ---|               |
   +--------+                               +---------------+

图 1:抽象的协议流程

图 1 中所示的抽象 OAuth 2.0 流程描述了四个角色之间的交互,包括以下步骤:

  • (A)客户机向资源所有者请求授权。可以直接向资源所有者发出授权请求(如图所示) ,或者最好是通过作为中介的授权服务器间接发出。

  • (B)客户端收到授权许可,这是一个代表资源所有者的授权的凭据,使用本规范中定义的四种许可类型之一或者使用扩展许可类型表示。授权许可类型取决于客户端请求授权所使用的方式以及授权服务器支持的类型。

  • (C)客户机通过与授权服务器进行身份验证并显示授权许可,从而请求访问令牌。

  • (D)授权服务器验证客户端身份和授权许可,若有效则颁发访问令牌。

  • (E)客户端从资源服务器请求受保护资源并出示访问令牌进行身份验证。

  • (F)资源服务器验证访问令牌,若有效则满足该请求。

客户端用于从资源所有者获得授权许可(步骤(A)和(B)所示)的更好方法是使用授权服务器作为中介,如 4.1 节 图 3 所示。

1.3. 授权许可

授权许可是一个代表资源所有者授权(访问受保护资源)的凭据,客户端用它来获取访问令牌。本规范定义了四种许可类型——授权码、隐式授权、资源所有者密码凭据和客户端凭据——以及用于定义其他类型的扩展性机制。

1.3.1. 授权码

授权码是通过使用授权服务器做为客户端与资源所有者的中介而获得。客户端不是直接从资源所有者请求授权,而是引导资源所有者至授权服务器(由在 [RFC2616] 中定义的用户代理),授权服务器之后引导资源所有者携带授权码回到客户端。

在引导资源所有者携带授权码返回客户端前,授权服务器会验证资源所有者身份并获得其授权。由于资源所有者只与授权服务器进行身份验证,所以客户端从未获取到资源所有者的凭据。

授权代码提供了一些重要的安全优势,如验证客户端的能力,以及将访问令牌直接传输给客户端,而不通过资源所有者的用户代理,这避免了将其暴露给其他人,包括资源所有者。

1.3.2. 隐式授权

隐式授权是一种简化的授权代码流程,为使用脚本语言(如 JavaScript)的浏览器中实现的客户端进行了优化。在隐式流程中,不是向客户发出授权代码,而是直接向客户发出一个访问令牌(作为资源所有者授权的结果)。这种许可类型是隐式的,因为没有中间凭据(如授权码)被颁发(之后用于获取访问令牌)。

当在隐式授权流程中颁发访问令牌时,授权服务器不对客户端进行身份验证。在某些情况下,客户端身份可以通过用于向客户端传送访问令牌的重定向 URI 验证。访问令牌可能会暴露给资源所有者,或者对资源所有者的用户代理有访问权限的其他应用程序。

隐式授权提高了一些客户端(如作为浏览器应用的客户端)的响应速度和效率,因为它减少了获取访问令牌所需的往返数量。然而,这种便利应该和采用隐式授权的安全影响作权衡,如那些在 10.3 和 10.16 节中所述的,尤其是当授权码许可类型可用的时候。

1.3.3. 资源所有者密码凭据

资源所有者的密码凭证(即用户名和密码)可以直接作为授权许可授予来获得访问令牌。只有在资源所有者和客户端之间存在高度信任的情况下(例如,客户端是设备操作系统的一部分或高度特权的应用程序),以及在其他授权授予类型不可用的情况下(如授权码),才应使用该凭证。

即使这种授予类型要求客户端直接访问资源所有者凭证,但资源所有者凭据仅被用于一次请求并被交换为访问令牌。通过长期有效的访问令牌或刷新令牌,这种许可类型可以消除客户端存储资源所有者凭据供以将来使用的需要。

1.3.4. 客户端凭据

当授权范围限于客户端控制下的受保护资源或事先与授权服务器商定的受保护资源时客户端凭据可以被用作为一种授权许可。典型的当客户端代表自己操作(客户端也是资源所有者)或者基于与授权服务器事先商定的授权请求对受保护资源的访问权限时,客户端凭据被用作为授权许可。

1.4. 访问令牌

访问令牌是用于访问受保护资源的凭据。访问令牌是一个字符串,表示发送给客户的授权。字符串对客户端通常是不透明的。令牌代表特定的访问范围和有效时间,由资源所有者授予,并由资源服务器和授权服务器使用。

令牌可以表示用于检索授权信息的标识符,也可以以可验证的方式自包含授权信息(即由一些数据和签名组成的令牌字符串)。为了让客户端使用令牌,可能需要额外的身份验证凭据,这超出了本规范的范围。

访问令牌提供了一个抽象层,将不同的授权结构(例如用户名和密码)替换为资源服务器可以理解的单个令牌。这种抽象使得发行的访问令牌比用于获得这些令牌的授权许可更加严格,同时也消除了资源服务器理解各种认证方法的需要。

基于资源服务器的安全要求访问令牌可以有不同的格式、结构及采用的方法(如加密属性)。访问令牌的属性和用于访问受保护资源的方法超出了本规范的范围,它们在 [RFC6750] 等配套规范中定义。

1.5. 刷新令牌

刷新令牌是用于获取访问令牌的凭据。刷新令牌由授权服务器发送给客户端,用于在当前访问令牌无效或过期时获取新的访问令牌,或者用于获取具有相同或更窄范围的其他访问令牌(访问令牌的生存期可能短于资源所有者授权的权限)。由授权服务器决定是否发出刷新令牌。如果授权服务器发出刷新令牌,那么在发出访问令牌(即图 1 中的步骤(D))时就会包含这个令牌。

刷新令牌是表示资源所有者授予客户端授权的字符串。字符串对客户端通常是不透明的。令牌表示用于检索授权信息的标识符。与访问令牌不同,刷新令牌仅用于授权服务器,从不发送到资源服务器。

+--------+                                           +---------------+
|        |--(A)------- Authorization Grant --------->|               |
|        |                                           |               |
|        |<-(B)----------- Access Token -------------|               |
|        |               & Refresh Token             |               |
|        |                                           |               |
|        |                            +----------+   |               |
|        |--(C)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(D)- Protected Resource --| Resource |   | Authorization |
| Client |                            |  Server  |   |     Server    |
|        |--(E)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(F)- Invalid Token Error -|          |   |               |
|        |                            +----------+   |               |
|        |                                           |               |
|        |--(G)----------- Refresh Token ----------->|               |
|        |                                           |               |
|        |<-(H)----------- Access Token -------------|               |
+--------+           & Optional Refresh Token        +---------------+

图 2:刷新过期的访问令牌

图 2 中的所示流程包含以下步骤:

  • (A)客户端通过与授权服务器进行身份验证并出示授权许可请求访问令牌。

  • (B)授权服务器对客户端进行身份验证并验证授权许可,若有效则颁发访问令牌和刷新令牌。

  • (C)客户端通过出示访问令牌向资源服务器请求受保护资源。

  • (D)资源服务器验证访问令牌,若有效则满足该请求。

  • (E)步骤(C)和(D)重复进行,直到访问令牌到期。如果客户端知道访问令牌已过期,则跳到步骤(G),否则它将继续发起另一个对受保护资源的请求。

  • (F)由于访问令牌是无效的,资源服务器返回无效令牌错误。

  • (G)客户端通过与授权服务器进行身份验证并出示刷新令牌,请求一个新的访问令牌。客户端请求的身份验证基于客户端类型和授权服务器策略。

  • (H)授权服务器对客户端进行身份验证并验证刷新令牌,若有效则颁发一个新的访问令牌(和可选的一个新的刷新令牌)。

步骤(C)、(D)、(E)和(F)在本规范的范围以外,如第 7 节中所述。

1.6. TLS 版本

每当本规范使用传输层安全性(TLS)时,TLS 的适当版本(或多个受支持的版本)将随着时间的推移而变化,这取决于广泛的部署和已知的安全漏洞。在撰写本文时,TLS 1.2 版 [RFC5246] 是最新的版本,但部署基础非常有限,可能无法立即实现。TLS 1.0 版 [RFC2246] 是部署最广泛的版本,将提供最广泛的互操作性。

实现还可以支持满足其安全需求的其他传输层安全机制。

1.7. HTTP 重定向

该规范广泛使用 HTTP 重定向,其中客户端或授权服务器将资源所有者的用户代理重定向到另一个目标。虽然本规范中的示例显示了 HTTP 302 状态代码的使用,但允许通过用户代理实现此重定向的任何其他方法,并将其视为实现细节。

1.8. 互操作性

OAuth 2.0 提供了丰富的具有明确的安全性的授权框架。然而,作为一个包含许多可选组件的丰富且高度可扩展的框架,本规范本身可能会产生大量不可互操作的实现。

此外,本规范保留了一些部分或完全未定义的必需组件(例如,客户端注册、授权服务器功能、端点发现)。如果没有这些组件,则必须针对特定的授权服务器和资源服务器手动和特定地配置客户端,以便进行互操作。

这一框架的设计明确期望今后的工作将界定实现全面的 web 级互操作性所必需的规范性的配置和扩展。

1.9. 符号约定

本规范中的关键词“必须”、“不能”、“必需的”、“要”、“不要”、“应该”、“不应该”、“推荐的”、“可以”以及“可选的”按 [RFC2119] 所述解释。

本规范使用 [RFC5234] 的扩展巴科斯-诺尔范式(ABNF)表示法。此外,来自“统一资源标识符(URI):通用语法” [RFC3986] 的规则 URI 引用也包含在内。

某些安全相关的术语按照 [RFC4949] 中定义的意思理解。这些术语包括但不限于:“攻击”、“身份认证”、“授权”、“证书”、“机密”,“凭据”,“加密”,“身份”,“记号”,“签名”,“信任”,“验证”和“核实”。

除非另有说明,所有协议参数的名称和值是大小写敏感的。

2.0 客户端注册

在开始协议之前,客户端要向授权服务器注册。客户端向授权服务器注册的方式超出了本规范的范围,但通常涉及终端用户与 HTML 注册表单的互动。

客户端注册不要求客户端与授权服务器之间的直接交互。在授权服务器支持下,注册可以依靠其他方式来建立信任关系并获取客户端的属性(如重定向 URI、客户端类型)。例如,可以使用自发的或第三方发布的断言完成注册,或者使用可信通道由授权服务器执行客户端发现。

当注册客户端时,客户端开发者应该:

  • 指定 2.1 节所述的客户端类型,

  • 提供它的如 3.1.2 节所述的客户端重定向 URI,且

  • 包含授权服务器要求的任何其他信息(如,应用名称、网址、描述、Logo 图片、接受法律条款等)。

2.1. 客户端类型

根据客户端与授权服务器安全地进行身份验证的能力(即维护客户端凭据机密性的能力),OAuth 定义了两种客户端类型:

  • 机密客户端

    能够维护其凭据保密性的客户端(例如,在安全服务器上运行的客户端,对客户端凭据的访问受到限制),或能够使用其他方式进行安全的客户端认证。

  • 公开客户端

    不能够维持其凭据的机密性(如客户端执行在由资源所有者使用的设备上,例如已安装的本地应用程序或基于 Web 浏览器的应用),且不能通过其他方式保证客户端身份验证的安全性。

客户端认证类型是基于授权服务器对安全身份验证的定义及其可接受的客户端凭据公开级别。授权服务器不应该对客户端类型做假设。

客户机可以实现为一组分布式组件,每个组件具有不同的客户机类型和安全上下文(例如,一个分布式客户端同时具有机密的基于服务器的组件和公开的基于浏览器的组件)。如果授权服务器不提供对这类客户端的支持,或不提供其注册方面的指导,客户端应该注册每个组件为一个单独的客户端。

本规范是围绕以下的客户端配置设计的:

  • Web 应用程序

    Web 应用是一个运行在 Web 服务器上的机密客户端。资源所有者通过其使用的设备上的用户代理里渲染的 HTML 用户界面访问客户端。资源所有者可以通过一个 HTML 用户界面访问资源所有者使用的设备上的用户代理客户端。客户端凭据以及发给客户端的任何访问令牌都存储在 web 服务器上,资源所有者无法访问它们。

  • 基于用户代理的应用程序

    基于用户代理的应用是一个公开客户端,客户端的代码从 Web 服务器下载,并在资源所有者使用的设备上的用户代理(如 Web 浏览器)中执行。协议数据和凭据对于资源所有者是可轻易访问的(且经常是可见的)。由于这些应用驻留在用户代理内,在请求授权时它们可以无缝地使用用户代理的功能。

  • 本机应用程序

    本机应用是一个安装、运行在资源所有者使用的设备上的公开客户端。协议数据和凭据对于资源所有者是可访问的。假定包含在应用程序中的任何客户端身份认证凭据可以被提取。另一方面,动态颁发的如访问令牌或者刷新令牌等凭据可以达到可接受的保护水平。至少,这些凭证会受到保护,免受应用程序可能与之交互的恶意服务器的攻击。在一些平台上,这些凭证可能被保护免于被驻留在相同设备上的其他应用接触。

2.2. 客户端标识

授权服务器颁发给已注册客户端客户端标识——一个客户端提供的代表其注册信息的唯一字符串。客户端标识不是一个秘密,它暴露给资源所有者并且不能单独用于客户端身份验证。客户端标识对于授权服务器是唯一的。

客户端的字符串大小本规范未定义。客户端应该避免对标识大小做假设。授权服务器应记录其发放的任何标识的大小。

2.3. 客户端身份验证

如果客户端类型是机密的,客户端和授权服务器建立符合授权服务器安全性要求的客户端身份验证方法。授权服务器可以接受符合其安全要求的任何形式的客户端身份验证。

机密客户端通常颁发(或建立)一组客户端凭据用于与授权服务器进行身份验证(例如,密码、公/私钥)。

授权服务器可以与公共客户端建立客户端身份验证方法。然而,授权服务器不能依靠公共客户端身份验证达到识别客户端的目的。

客户端在每次请求中不能使用一个以上的身份验证方法。

2.3.1. 客户端密码

拥有客户端密码的客户端可以使用 [RFC2617] 中定义的 HTTP 基本身份验证方案与授权服务器进行身份验证。客户端标识使用按照 附录 B 的“application/x-www-form-urlencoded”编码算法编码,编码后的值用作用户名;客户端密码使用相同的算法编码并用作密码。授权服务器必须支持 HTTP 基本身份验证方案,用于验证被颁发客户端密码的客户端的身份。

例如(额外的换行仅用于显示目的):

Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3

此外,授权服务器可以使用下列参数支持在请求正文中包含客户端凭据:

  • client_id

    必需的。如 2.2 节所述的注册过程中颁发给客户端的客户端标识。

  • client_secret

    必需的。客户端密钥。若客户端密钥是一个空字符串则可以忽略该参数。

不建议使用这两个参数在请求正文中包含客户端凭据,并且应限于无法直接使用 HTTP 基本身份验证方案(或其他基于密码的 HTTP 身份验证方案)的客户端。参数只能在请求正文中传输,不能包含在请求 URI 中。

例如,一个刷新访问令牌(第 6 节)的请求使用正文参数(额外的换行仅用于显示目的):

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

grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA&client_id=s6BhdRkqt3&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw

当使用密码身份验证发送请求时,授权服务器必须要求使用如 1.6 所述的 TLS。

由于此客户端身份验证方法涉及密码,因此授权服务器必须保护使用密码的任何端点免受暴力攻击。

2.3.2. 其他身份验证方法

授权服务器可以支持任何与其安全要求匹配的合适的 HTTP 身份验证方案。当使用其他身份验证方法时,授权服务器必须定义客户端标识(注册记录)和认证方案之间的映射。

2.4. 未注册的客户端

本规范不排除使用未注册的客户端。然而,使用这样的客户端超出了本规范的范围,并需要额外的安全性分析并审查其互操作性影响。

3. 协议端点

授权过程采用了两个授权服务器端点(HTTP 资源):

  • 授权端点——客户端用其通过用户代理重定向从资源所有者获取授权。

  • 令牌端点——客户端用其将授权许可交换为访问令牌,通常伴有客户端身份验证。

以及一种客户端端点:

  • 重定向端点——授权服务器用其通过资源所有者用户代理向客户端返回含有授权凭据的响应。

并不是每种授权许可类型都采用两种端点。

扩展许可类型可以按需定义其他端点。

3.1. 授权端点

授权端点用于与资源所有者交互来获取授权许可。 授权服务器必须先验证资源所有者的身份。 授权服务器对资源所有者进行身份验证的方式(例如,用户名和密码登录、会话 cookies)超出了本规范的范围。

客户端获得授权端点位置的方式超出了本文档范围,但该位置通常在服务文档中提供。

端点 URI 可以包含“application/x-www-form-urlencoded”格式(按附录 B)的查询部分([RFC3986] 的 3.4 节),当添加额外的查询参数时必须保留该部分。端点 URI 不得包含该部分的任何内容。

由于对授权端点的请求会导致用户身份验证和明文凭证的传输(在 HTTP 响应中),因此授权服务器在向授权端点发送请求时必须要求使用第 1.6 节所述的 TLS。

授权服务器对于授权端点必须支持使用 HTTP“GET”方法 [RFC2616],也可以支持使用“POST”的方法。

不带值发送的参数必须从请求中省略。授权服务器必须忽略无法识别的请求参数。请求和响应参数不能重复。

3.1.1. 响应类型

授权端点被授权码类型和隐式授权类型流程使用。客户端使用下列参数通知授权服务器期望的许可类型:

  • response_type

    必需的。该值必须是第 4.1.1 节所述的用于请求授权码的“代码”、第 4.2.1 节所述的用于请求访问令牌(隐式授权)的“令牌”或第 8.4 节所述的注册扩展值之一。

扩展响应类型可以包含一个空格(%x20)分隔的值的列表,值的顺序并不重要(例如,响应类型“a b”与“b a”相同)。 这样的复合响应类型的含义由他们各自的规范定义。

如果授权请求缺少“response_type”参数,或者响应类型不被理解,那么授权服务器必须返回一个 4.1.2.1 所述的错误响应。

3.1.2. 重定向端点

在完成与资源所有者的交互后,授权服务器引导资源所有者的用户代理返回到客户端。授权服务器重定向用户代理至客户端的重定向端点,该端点是之前在客户端注册过程中或者发起授权请求时与授权服务器建立的。

重定向端点 URI 必须是如 [RFC3986] 的 3.4 节所述的绝对 URI。端点 URI 可以包含“application/x-www-form-urlencoded”格式(按附录 B)的查询部分([RFC3986] 的 3.4 节),当添加额外的查询参数时必须保留该部分。端点 URI 不得包含该部分的任何内容。

3.1.2.1. 端点请求的机密性

当所请求的响应类型是“code”或“token”时,或者当重定向请求将引起在机密凭据通过公开网络传输时,重定向端点应该使用 1.6 节所述的 TLS。本规范没有强制使用 TLS,因为在撰写本规范时,要求客户端部署 TLS 对许多客户端开发人员来说是一个重大障碍。如果 TLS 不可用,授权服务器应该在重定向之前就不安全的端点向资源所有者发出警告(例如,在授权请求期间显示一条信息)。

传输层安全的缺乏可能对客户端及它被授权访问的受保护资源的安全具有严重影响。当授权过程被客户端用作授权最终用户身份验证的一种形式(例如,第三方登录服务)时,传输层安全性的使用尤为关键。

3.1.2.2. 注册要求

授权服务器必须要求下列客户端注册它们的重定向端点:

  • 公开客户端。

  • 采用隐式授权类型的机密客户端。

授权服务器应该要求所有客户端在使用授权端点之前注册其重定向端点。

授权服务器应该要求客户端提供完整的重定向 URI(客户端可以使用“state”请求参数实现每请求自定义)。如果要求完整的重定向 URI 注册不可行,授权服务器应该要求注册 URI 方案、授权和路径(允许客户端在请求授权时仅动态更改重定向 URI 的查询部分)。

授权服务器可以允许客户端注册多个重定向端点。

缺少重定向 URI 注册的要求,可能使攻击者如 10.15 所述将授权端点用作自由重定向端点。

3.1.2.3. 动态配置

客户端注册多个重定向 URI 时,如果只有部分或没有重定向 URI 被注册,客户端必须使用“redirect_uri”请求参数在授权请求中包含重定向 URI。

当授权请求中包含重定向 URI 时,如果存在已注册的重定向 URI,授权服务器必须将收到的值与 [RFC3986] 第 6 节中定义的至少一个已注册重定向 URI(或 URI 组件)进行比较和匹配。如果客户端注册包含完整重定向 URI,则授权服务器必须使用 [RFC3986] 第 6.2.1 节中定义的简单字符串比较方法来比较这两个 URI。

3.1.2.4. 无效端点

如果由于缺失、无效或不匹配的重定向 URI 而验证失败,授权服务器应该通知资源所有者该错误且不能重定向用户代理到无效的重定向 URI。

3.1.2.5. 端点内容

对客户端端点的重定向请求通常会产生一个 HTML 文档响应,该响应由用户代理处理。如果 HTML 响应直接作为重定向请求的结果提供,则 HTML 文档中包含的任何脚本都将在完全访问重定向 URI 及其包含的凭据的情况下执行。

客户端不应该在重定向端点的响应中包含任何第三方的脚本(例如,第三方数据分析、社交插件、广告网络)。相反,它应该从 URI 中提取凭据,并再次将用户代理重定向到另一个端点,而不暴露凭据(在 URI 中或其他地方)。如果包含第三方脚本,客户端必须确保它自己的脚本(用于从 URI 中提取凭据并从 URI 中删除)将首先执行。

3.2. 令牌端点

客户端通过提交它的授权许可或刷新令牌从令牌端点获取访问令牌。令牌端点被用于除了隐式授权类型(因为访问令牌是直接颁发的)外的所有授权许可中。

客户端通过何种方式获取令牌端点的位置超出了本文档范围,但该位置通常在服务文档中提供。

端点 URI 可以包含“application/x-www-form-urlencoded”格式(按附录 B)的查询部分([RFC3986] 的 3.4 节),当添加额外的查询参数时必须保留该部分。端点 URI 不得包含该部分的任何内容。

由于向令牌端点的请求产生明文凭据的传输(在 HTTP 请求和响应中),当向令牌端点发送请求时,授权服务器必须要求使用 1.6 节所述的 TLS。

当发起访问令牌请求时,客户端必须使用 HTTP “POST”方法。

不带值发送的参数必须从请求中省略。授权服务器必须忽略无法识别的请求参数。请求和响应参数不能重复。

3.2.1. 客户端身份验证

在向令牌端点发起请求时,机密客户端或其他被颁发客户端凭据的客户端必须如 2.3 节所述与授权服务器进行身份验证。客户端身份验证用于:

  • 强制将刷新令牌和授权代码绑定到颁发的客户端。当授权码通过不安全的通道传输到重定向端点,或者重定向 URI 尚未完全注册时,客户端身份验证至关重要。

  • 通过禁用客户端或更改其凭据来恢复被攻击的客户端,从而防止攻击者滥用窃取的刷新令牌。更改一组客户端凭据要比撤销一整套刷新令牌快得多。

  • 实现身份验证管理的最佳实践,要求定期轮换令牌。轮换一整套刷新令牌可能会很困难,而轮换一组客户端凭据则要容易得多。

在向令牌端点发送请求时,客户端可以使用“client_id”请求参数标识自己。向令牌端点的“authorization_code”和“grant_type”请求中,未经身份验证的客户端必须发送它的“client_id”,以防止自己无意中接受一个用于有不同“client_id”的客户端的代码。这保护了客户端免于被替换授权码。(它没有对受保护资源提供额外的安全。)

3.3. 访问令牌作用域

授权端点和令牌端点允许客户端使用“scope”请求参数指定访问请求的作用域。反过来,授权服务器使用“scope”响应参数通知客户端颁发的访问令牌的作用域。

scope 参数的值表示为以空格分隔,大小写敏感的字符串。 该字符串由授权服务器定义。如果该值包含多个以空格分隔的字符串,它们的顺序无关紧要,每个字符串都会向请求范围添加一个额外的访问范围。

scope = scope-token *( SP scope-token )
scope-token = 1*( %x21 / %x23-5B / %x5D-7E )

根据授权服务器策略或资源所有者的指示,授权服务器可以完全或部分忽略客户端请求的范围。如果颁发的访问令牌作用域与客户端请求的作用域不同,则授权服务器必须包含“作用域”响应参数,以通知客户端实际许可的作用域。

如果客户端在请求授权时忽略了 scope 参数,则授权服务器必须使用预定义的默认值处理该请求,或者使请求失败以指示无效作用域。授权服务器应记录其范围要求和默认值(如果定义)。

4. 获得授权

为了请求访问令牌,客户端从资源所有者处获得授权。授权以授权许可的形式表示,客户端使用授权许可请求访问令牌。OAuth 定义了四种授权类型:授权码、隐式授权、资源所有者密码凭据和客户端凭据。它还提供了一种扩展机制来定义额外的授权类型。

4.1. 授权码许可

授权码许可类型用于获取访问令牌和刷新令牌,并针对机密客户端进行了优化。由于这是一个基于重定向的流程,客户端必须能够与资源所有者的用户代理(通常是 Web 浏览器)进行交互并能够接收来自授权服务器的传入请求(通过重定向)。

   +----------+
   | Resource |
   |   Owner  |
   |          |
   +----------+
        ^
        |
       (B)
   +----|-----+          Client Identifier      +---------------+
   |         -+----(A)-- & Redirection URI ---->|               |
   |  User-   |                                 | Authorization |
   |  Agent  -+----(B)-- User authenticates --->|     Server    |
   |          |                                 |               |
   |         -+----(C)-- Authorization Code ---<|               |
   +-|----|---+                                 +---------------+
     |    |                                         ^      v
    (A)  (C)                                        |      |
     |    |                                         |      |
     ^    v                                         |      |
   +---------+                                      |      |
   |         |>---(D)-- Authorization Code ---------'      |
   |  Client |          & Redirection URI                  |
   |         |                                             |
   |         |<---(E)----- Access Token -------------------'
   +---------+       (w/ Optional Refresh Token)

注:说明步骤(A)、(B)和(C)的直线因为通过用户代理而被分为两部分。

图 3:授权码流程

在图 3 中所示的流程包括以下步骤:

  • (A)客户端通过将资源所有者的用户代理定向到授权端点来开始流程。客户端包括它的客户端标识、请求范围、本地状态和重定向 URI,一旦访问被许可(或拒绝)授权服务器将重定向用户代理回到该 URI。

  • (B)授权服务器验证资源拥有者的身份(通过用户代理),并确定资源所有者是否授予或拒绝客户端的访问请求。

  • (C)假设资源所有者许可访问,授权服务器使用之前(在请求时或客户端注册时)提供的重定向 URI 重定向用户代理回到客户端。重定向 URI 包括授权码和之前客户端提供的任何本地状态。

  • (D)客户端通过包含在上一步中接收的授权代码,从授权服务器的令牌端点请求访问令牌。发出请求时,客户端会和授权服务器进行身份验证。客户端包括用于获取验证授权代码的重定向 URI。

  • (E)授权服务器对客户端进行身份验证,验证授权代码,并确保接收的重定向 URI 与在步骤(C)中用于重定向客户端的 URI 相匹配。如果验证成功,授权服务器使用访问令牌和刷新令牌(可选)进行响应。

4.1.1. 授权请求

客户端通过按 附录 B 使用“application/x-www-form-urlencoded”格式向授权端点 URI 的查询部分添加下列参数构造请求 URI:

  • response_type

    必需的。值必须被设置为“code”。

  • client_id

    必需的。如 2.2 节所述的客户端标识。

  • redirect_uri

    可选的。如 3.1.2 节所述。

  • scope

    可选的。如 3.3 节所述的访问请求的作用域。

  • state

    推荐的。客户端用于维护请求和回调之间的状态的不透明值。授权服务器在将用户代理重定向回客户端时包含此值。该参数应用于防止第 10.12 节所述跨域请求伪造。

客户端使用 HTTP 重定向响应将资源所有者重定向到构造的 URI,或者采用用户代理支持的其他方法 。 例如,客户端重定向用户代理发起下述使用 TLS 的 HTTP 请求(额外的换行仅用于显示目的):

GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com

授权服务器验证该请求,确保所有需要的参数已提交且有效。如果请求是有效的,授权服务器对资源所有者进行身份验证并获得授权决策(通过询问资源所有者或通过其他方式获得许可)。

确定决策后,授权服务器使用 HTTP 重定向响应或通过用户代理提供的其他方式将用户代理定向到客户端提供的重定向 URI。

4.1.2. 授权响应

如果资源所有者许可访问请求,授权服务器将发布一个授权代码,并通过使用“application/x-www-form-urlencoded”格式,按照附录 B 向重定向 URI 的查询部分添加以下参数,并将其发送给客户端:

  • code

    必需的。授权服务器生成的授权代码。授权码必须在发布后不久到期,以降低泄漏风险。建议授权代码的最长生存时间为 10 分钟。客户不得多次使用授权码。如果一个授权码被多次使用,授权服务器必须拒绝该请求,并在可能的情况下撤销之前基于该授权码颁发的所有令牌。授权代码绑定到客户端标识符和重定向 URI。

  • state

    如果客户端授权请求中存在“state”参数,则为必须的。该值从客户端获取。

例如,授权服务器通过发送以下 HTTP 响应重定向用户代理:

HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz

客户端必须忽略无法识别的响应参数。本规范未定义授权码字符串大小。客户应该避免对代码值大小进行假设。授权服务器应该记录它发出的任何值的大小。

4.1.2.1. 错误响应

如果请求因重定向 URI 丢失、无效或不匹配而失败,或者如果客户端标识符丢失或无效,授权服务器应将错误通知资源所有者,并且不得自动将用户代理重定向到无效的重定向 URI。

如果资源所有者拒绝访问请求,或者请求因缺少或无效的重定向 URI 以外的原因而失败,授权服务器将根据附录 B,通过使用“application/x-www-form-urlencoded”格式向重定向 URI 的查询部分添加以下参数来通知客户端:

  • error

    必需的。下列 ASCII[USASCII] 错误代码之一:

    • invalid_request

      请求缺少必需的参数、包含无效的参数值、包含重复参数或格式不正确。

    • unauthorized_client

      客户端未被授权使用此方法请求授权码。

    • access_denied

      资源所有者或授权服务器拒绝该请求。

    • unsupported_response_type

      授权服务器不支持使用此方法获得授权码。

    • invalid_scope

      请求的范围无效,未知的或格式不正确。

    • server_error

      授权服务器遇到意外情况,无法满足请求。(之所以需要此错误代码,是因为无法通过 HTTP 重定向将 500 内部服务器错误 HTTP 状态代码返回给客户端。)

    • temporarily_unavailable

      由于服务器临时超载或维护,授权服务器当前无法处理请求。(需要此错误代码,因为无法通过 HTTP 重定向将 503 服务不可用的 HTTP 状态代码返回给客户端。)

    “error”参数的值不能包含集合 %x20-21 / %x23-5B / %x5D-7E 以外的字符。

  • error_description

    可选的。提供额外的人类可读的 ASCII[USASCII] 信息文本,用于协助客户端开发人员理解所发生的错误。

    “error_description”参数的值不能包含集合 %x20-21 / %x23-5B / %x5D-7E 以外的字符。

  • error_uri

    可选的。指向包含有关错误信息的人类可读的网页 URI,用于向客户端开发人员提供关于该错误的额外信息。

    “error_uri”参数值必须符合 URI 参考语法,因此不能包含集合 %x21 / %x23-5B / %x5D-7E 以外的字符。

  • state

    如果客户端授权请求中存在“state”参数,则为必须的。该值从客户端获取。

例如,授权服务器通过发送以下 HTTP 响应重定向用户代理:

HTTP/1.1 302 Found
Location: https://client.example.com/cb?error=access_denied&state=xyz

4.1.3. 访问令牌请求

客户端通过使用附录 B 中的“application/x-www-form-urlencoded”格式发送以下参数向令牌端点发出请求,HTTP 请求实体体中的字符编码为 UTF-8:

  • grant_type

    必需的。值必须被设置为“authorization_code”。

  • code

    必需的,从授权服务器收到的授权码。

  • redirect_uri

    必需的,如第 4.1.1 节所述,如果授权请求中包含“redirect_uri”参数,那么此值必须相同。

  • client_id

    必需的,如果客户端没有如 3.2.1 节所述与授权服务器进行身份认证。

如果客户端类型是机密的或客户端被颁发了客户端凭据(或选定的其他身份验证要求),客户端必须如按照第 3.2.1 节所述与授权服务器进行身份验证。

例如,客户端使用 TLS 发起如下的 HTTP 请求(额外的换行符仅用于显示目的):

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

授权服务器必须:

  • 要求机密客户端或任何被颁发了客户端凭据(或有其他身份验证要求)的客户端进行客户端身份验证,

  • 如果包含客户端身份验证,则对客户端进行身份验证,

  • 确保将授权码颁发给经过身份验证的机密客户端,或者如果客户端是公开的,请确保将代码颁发给请求中的“client_id”,

  • 验证授权码是有效的,并

  • 如果“redirect_uri”参数包含在第 4.1.1 节所述的初始授权请求中,则确保给出“redirect_uri”参数,且如果包含则确保它们的值相同。

4.1.4. 访问令牌响应

如果访问令牌请求有效且被授权,授权服务器会发出如第 5.1 节所述的访问令牌和可选的刷新令牌。如果请求客户端身份验证失败或无效,授权服务器将返回如第 5.2 节所述的错误响应。

一个成功响应的样例:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token":"2YotnFZFEjr1zCsicMWpAA",
  "token_type":"example",
  "expires_in":3600,
  "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
  "example_parameter":"example_value"
}

4.2. 隐式授权

隐式授权类型用于获取访问令牌(它不支持颁发刷新令牌),并且针对已知可操作特定重定向 URI 的公共客户端进行了优化。这些客户端通常使用 JavaScript 等脚本语言在浏览器中实现。

由于这是一个基于重定向的流程,客户端必须能够与资源所有者的用户代理(通常是 Web 浏览器)进行交互并能够接收来自授权服务器的传入请求(通过重定向)。

与授权码许可类型不同,在这种授权类型中,客户端分别发出授权请求和访问令牌请求,客户端接收访问令牌作为授权请求的结果。

隐式授权类型不包括客户端身份验证,并且依赖于资源所有者的存在和重定向 URI 的注册。 因为访问令牌被编码到重定向 URI 中,所以它可能会暴露给资源所有者和驻留在同一设备上的其他应用程序。

 +----------+
 | Resource |
 |  Owner   |
 |          |
 +----------+
      ^
      |
     (B)
 +----|-----+          Client Identifier     +---------------+
 |         -+----(A)-- & Redirection URI --->|               |
 |  User-   |                                | Authorization |
 |  Agent  -|----(B)-- User authenticates -->|     Server    |
 |          |                                |               |
 |          |<---(C)--- Redirection URI ----<|               |
 |          |          with Access Token     +---------------+
 |          |            in Fragment
 |          |                                +---------------+
 |          |----(D)--- Redirection URI ---->|   Web-Hosted  |
 |          |          without Fragment      |     Client    |
 |          |                                |    Resource   |
 |     (F)  |<---(E)------- Script ---------<|               |
 |          |                                +---------------+
 +-|--------+
   |    |
  (A)  (G) Access Token
   |    |
   ^    v
 +---------+
 |         |
 |  Client |
 |         |
 +---------+

注:说明步骤(A)和(B)的直线因为通过用户代理而被分为两部分。

图 4:隐式授权流程

图 4 中的所示流程包含以下步骤:

  • (A)客户端通过将资源所有者的用户代理定向到授权端点来开始流程。客户端包括它的客户端标识、请求范围、本地状态和重定向 URI,一旦访问被许可(或拒绝)授权服务器将重定向用户代理回到该 URI。

  • (B)授权服务器验证资源拥有者的身份(通过用户代理),并确定资源所有者是否授予或拒绝客户端的访问请求。

  • (C)假设资源所有者授予访问权限,授权服务器使用之前提供的重定向 URI 将用户代理重定向回客户端。重定向 URI 在 URI 片段中包含访问令牌。

  • (D)用户代理通过向 Web 托管的客户端资源(不包括根据 [RFC2616] 的片段)发出请求来遵循重定向指令。 用户代理在本地保留片段信息。

  • (E)Web 托管的客户端资源返回一个网页(通常是带有嵌入式脚本的 HTML 文档),该网页能够访问包含用户代理保留的片段在内的完整重定向 URI 并提取包含在片段中的访问令牌(和其他参数)。

  • (F)用户代理在本地执行由 Web 托管的客户端资源提供的脚本,从而提取访问令牌。

  • (G)用户代理传送访问令牌给客户端。

参见 1.3.2 节和第 9 节了解使用隐式授权的背景。参见 10.3 节和 10.16 节了解当使用隐式授权时重要的安全注意事项。

4.2.1. 授权请求

客户端通过按 附录 B 使用“application/x-www-form-urlencoded”格式向授权端点 URI 的查询部分添加下列参数构造请求 URI:

  • response_type

    必需的。值必须设置为“token”。

  • client_id

    必需的。如 2.2 节所述的客户端标识。

  • redirect_uri

    可选的。如 3.1.2 节所述。

  • scope

    可选的。如 3.3 节所述的访问请求的范围。

  • state

    推荐的。客户端用来维护请求和回调之间状态的不透明值。授权服务器在将用户代理重定向回客户端时包含此值。该参数应该用于防止跨站点请求伪造,如第 10.12 节所述。

客户端使用 HTTP 重定向响应或通过用户代理可用的其他方式将资源所有者定向到构造的 URI。

例如,客户端定向用户代理使用 TLS 发出以下 HTTP 请求(额外的换行仅用于显示目的):

GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com

授权服务器验证请求以确保所有必需的参数都存在且有效。 授权服务器必须验证它将访问令牌重定向到的重定向 URI 是否与第 3.1.2 节所述的客户端注册的重定向 URI 匹配。

如果请求是有效的,授权服务器对资源所有者进行身份验证并获得授权决策(通过询问资源所有者或通过经由其他方式确定批准)。

当确定决策后,授权服务器使用 HTTP 重定向响应向提供的客户端重定向 URI 定向用户代理,或者通过经由用户代理至该 URI 的其他可行方法

当确定决策后,授权服务器使用 HTTP 重定向响应或通过用户代理可用的其他方式将用户代理定向到重定向 URI。

4.2.2. 访问令牌响应

如果资源所有者许可访问请求,授权服务器颁发访问令牌,通过使用按 附录 B )的“application/x-www-form-urlencoded”格式向重定向 URI 的片段部分添加下列参数传递访问令牌至客户端:

  • access_token

    必需的。授权服务器颁发的访问令牌。

  • token_type

    必需的。如 7.1 节所述的颁发的令牌的类型。值是大小写敏感的。

  • expires_in

    推荐的。以秒为单位的访问令牌生命周期。例如,值“3600”表示访问令牌将在从生成响应时的 1 小时后到期。如果省略,则授权服务器应该通过其他方式提供过期时间,或者记录默认值。

  • scope

    若与客户端请求的范围相同则可选,否则必需。如 3.3 节所述的访问令牌的范围。

  • state

    如果客户端授权请求中存在“state”参数,则必需。从客户端收到的具体值。

授权服务器不能颁发刷新令牌。

例如,授权服务器通过发送以下 HTTP 响应重定向用户代理:(额外的换行符仅用于显示目的):

HTTP/1.1 302 Found
Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&token_type=example&expires_in=3600

开发人员应注意,一些用户代理不支持在 HTTP“Location”响应头字段中包含片段部分。这些客户端需要使用除了 3xx 重定向响应以外的其他方法来重定向客户端——例如,返回一个 HTML 页面,其中包含一个具有链接到重定向 URI 操作的“继续”按钮。

客户端必须忽略无法识别的响应参数。 本规范未定义访问令牌字符串大小。 客户端应避免对价大小做出假设。 授权服务器应该记录它发出的任何值的大小。

4.2.2.1. 错误响应

如果请求因重定向 URI 丢失、无效或不匹配而失败,或者如果客户端标识符丢失或无效,授权服务器应将错误通知资源所有者,并且不得自动将用户代理重定向到无效的重定向 URI。

如果资源所有者拒绝访问请求,或者请求因缺少或无效的重定向 URI 以外的原因而失败,授权服务器将根据附录 B,通过使用“application/x-www-form-urlencoded”格式向重定向 URI 的查询部分添加以下参数来通知客户端:

  • error

    必需的。下列 ASCII[USASCII] 错误代码之一:

    • invalid_request

      请求缺少必需的参数、包含无效的参数值、包含重复参数或格式不正确。

    • unauthorized_client

      客户端未被授权使用此方法请求授权码。

    • access_denied

      资源所有者或授权服务器拒绝该请求。

    • unsupported_response_type

      授权服务器不支持使用此方法获得授权码。

    • invalid_scope

      请求的范围无效,未知的或格式不正确。

    • server_error

      授权服务器遇到意外情况,无法满足请求。(之所以需要此错误代码,是因为无法通过 HTTP 重定向将 500 内部服务器错误 HTTP 状态代码返回给客户端。)

    • temporarily_unavailable

      由于服务器临时超载或维护,授权服务器当前无法处理请求。(需要此错误代码,因为无法通过 HTTP 重定向将 503 服务不可用的 HTTP 状态代码返回给客户端。)

    “error”参数的值不能包含集合 %x20-21 / %x23-5B / %x5D-7E 以外的字符。

  • error_description

    可选的。提供额外信息的人类可读的 ASCII[USASCII]文本,用于协助客户端开发人员理解所发生的错误。

    “error_description”参数的值不能包含集合%x20-21 /%x23-5B /%x5D-7E 以外的字符。

  • error_uri

    可选的。指向包含有关错误信息的人类可读的网页 URI,用于向客户端开发人员提供关于该错误的额外信息。

    “error_uri”参数值必须符合 URI 参考语法,因此不能包含集合 %x21 / %x23-5B /%x5D-7E 以外的字符。

  • state 如果客户端授权请求中存在“state”参数,则为必须的。该值从客户端获取。

例如,授权服务器通过发送以下 HTTP 响应重定向用户代理:

HTTP/1.1 302 Found
Location: https://client.example.com/cb#error=access_denied&state=xyz

4.3. 资源所有者密码凭据许可

资源所有者密码凭证授予类型适用于资源所有者与客户端具有信任关系的情况,例如设备操作系统或高特权应用程序。授权服务器在启用此授权类型时应特别小心,并且仅在其他流程不可行时才允许它。

此授权类型适用于能够获取资源所有者凭据(用户名和密码,通常使用交互式表单)的客户端。它还用于使用直接身份验证方案(例如 HTTP Basic 或 Digest 身份验证)将现有客户端迁移到 OAuth,方法是将存储的凭据转换为访问令牌。

 +----------+
 | Resource |
 |  Owner   |
 |          |
 +----------+
      v
      |    Resource Owner
     (A) Password Credentials
      |
      v
 +---------+                                  +---------------+
 |         |>--(B)---- Resource Owner ------->|               |
 |         |         Password Credentials     | Authorization |
 | Client  |                                  |     Server    |
 |         |<--(C)---- Access Token ---------<|               |
 |         |    (w/ Optional Refresh Token)   |               |
 +---------+                                  +---------------+

图 5:资源所有者密码凭据流程

图 5 中的所示流程包含以下步骤:

  • (A)资源所有者提供给客户端它的用户名和密码。

  • (B)客户端通过携带从资源所有者收到的凭据,从授权服务器的令牌端点请求访问令牌。发出请求时,客户端向授权服务器进行身份验证。

  • (C)授权服务器对客户端进行身份验证,验证资源所有者的凭证,如果有效,颁发访问令牌。

4.3.1. 授权请求和响应

客户端获取资源所有者凭据的方法超出了本规范的范围。 一旦获得访问令牌,客户端必须丢弃凭据。

4.3.2. 访问令牌请求

客户端通过使用按 附录 B “application/x-www-form-urlencoded”格式在 HTTP 请求实体正文中发送下列 UTF-8 字符编码的参数向令牌端点发起请求:

  • grant_type

    必需的。值必须设置为“password”。

  • username

    必需的。资源所有者的用户名。

  • password

    必需的。资源所有者的密码。

  • scope

    可选的。如 3.3 节所述的访问请求的范围。

如果客户端类型是机密的或客户端被颁发了客户端凭据(或选定的其他身份验证要求),客户端必须如 3.2.1 节所述与授权服务器进行身份验证。

例如,客户端在传输层安全下发起如下 HTTP 请求(额外的换行仅用于显示目的):

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=johndoe&password=A3ddj3w

授权服务器必须:

  • 要求对机密客户端或任何已颁发客户端凭据(或具有其他身份验证要求)的客户端进行客户端身份验证,

  • 若包括了客户端身份验证,验证客户端身份,并

  • 使用其现有的密码验证算法验证资源所有者的密码凭据。

由于这种访问令牌请求使用了资源所有者的密码,授权服务器必须保护端点抵御暴力攻击(例如,使用速率限制或生成警报)

4.3.3. 访问令牌响应

如果访问令牌请求有效且被授权,授权服务器会如第 5.1 节所述发出访问令牌和可选的刷新令牌。 如果请求未通过客户端身份验证或无效,授权服务器将如第 5.2 节所述返回错误响应。

一个成功响应的样例:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token":"2YotnFZFEjr1zCsicMWpAA",
  "token_type":"example",
  "expires_in":3600,
  "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
  "example_parameter":"example_value"
}

4.4. 客户端凭据许可

当客户端请求访问它所控制的,或者事先与授权服务器协商(所采用的方法超出了本规范的范围)的其他资源所有者的受保护资源时,客户端可以只使用它的客户端凭据(或者其他受支持的身份验证方法)请求访问令牌。

客户端凭据许可类型必须只能由机密客户端使用。

 +---------+                                  +---------------+
 |         |                                  |               |
 |         |>--(A)- Client Authentication --->| Authorization |
 | Client  |                                  |     Server    |
 |         |<--(B)---- Access Token ---------<|               |
 |         |                                  |               |
 +---------+                                  +---------------+

图 6:客户端凭证流程

图 6 中的所示流程包含以下步骤:

  • (A)客户端与授权服务器进行身份验证并向令牌端点请求访问令牌。

  • (B)授权服务器对客户端进行身份验证,如果有效,则颁发访问令牌。

4.4.1. 授权请求和响应

由于客户端身份验证被用作授权许可,所以不需要额外的授权请求。

4.4.2. 访问令牌请求

客户端通过使用附录 B 中的“application/x-www-form-urlencoded”格式发送以下参数向令牌端点发出请求,HTTP 请求实体体中的字符编码为 UTF-8:

  • grant_type

    必需的。值必须设置为“client_credentials”。

  • scope

    可选的。如 3.3 节所述的访问请求的范围。

客户端必须如 3.2.1 所述与授权服务器进行身份验证。

例如,客户端在传输层安全下发起如下 HTTP 请求(额外的换行仅用于显示目的):

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials

授权服务器必须对客户端进行身份验证。

4.4.3. 访问令牌响应

如果访问令牌请求有效且已授权,则授权服务器会如第 5.1 节所述颁发访问令牌和可选的刷新令牌。 如果请求未通过客户端身份验证或无效,授权服务器将返回如第 5.2 节所述的错误响应。

一个成功响应的样例:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token":"2YotnFZFEjr1zCsicMWpAA",
  "token_type":"example",
  "expires_in":3600,
  "example_parameter":"example_value"
}

4.5. 扩展许可

客户端通过使用绝对 URI(由授权服务器定义)作为令牌端点的“grant_type”参数的值来指定授权类型,并通过添加任何必要的附加参数来使用扩展授权类型。

例如,要使用 [OAuth-SAML2] 定义的安全断言标记语言 (SAML) 2.0 断言授权类型请求访问令牌,客户端可以使用 TLS 发出以下 HTTP 请求(额外的换行符仅用于显示目的):

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Asaml2bearer&assertion=PEFzc2VydGlvbiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDU[...为简洁起见省略...]aG5TdGF0ZW1lbnQ-PC9Bc3NlcnRpb24-

如果访问令牌请求是有效的且被授权,授权服务器如 5.1 节所述颁发访问令牌以及可选的刷新令牌。如果请求因客户端身份验证失败或无效,授权服务器如 5.2 节所述的返回错误响应。

5. 颁发访问令牌

如果访问令牌请求是有效的且被授权,授权服务器如 5.1 节所述颁发访问令牌以及可选的刷新令牌。如果请求因客户端身份验证失败或无效,授权服务器如 5.2 节所述的返回错误响应。

5.1. 成功的响应

授权服务器颁发访问令牌和可选的刷新令牌,通过向 HTTP 响应实体正文中添加下列参数并使用 200(OK)状态码构造响应:

  • access_token

    必需的。授权服务器颁发的访问令牌。

  • token_type

    必需的。如 7.1 节所述的颁发的令牌的类型。值是大小写敏感的。

  • expires_in

    推荐的。以秒为单位的访问令牌生命周期。例如,值“3600”表示访问令牌将在从生成响应时的 1 小时后到期。如果省略,则授权服务器应该通过其他方式提供过期时间,或者记录默认值。

  • refresh_token

    可选的。刷新令牌,可以用于如第 6 节所述使用相同的授权许可获得新的访问令牌。

  • scope

    可选的,若与客户端请求的范围相同;否则,必需的。如 3.3 节所述的访问令牌的范围。

这些参数使用 [RFC4627] 定义的“application/json”媒体类型包含在 HTTP 响应实体正文中。将每个参数添加到最高结构级别并序列化为 JavaScript 对象表示法(JSON)的结构。参数名称和字符串值作为 JSON 字符串类型包含。数值的值作为 JSON 数字类型包含。参数顺序无关且可以变化。

在任何包含令牌、凭据或其他敏感信息的响应中,授权服务器必须在其中包含值为“no-store”的 HTTP“Cache-Control”响应头 [RFC2616],和值为“no-cache”的“Pragma”响应头 [RFC2616]。例如:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token":"2YotnFZFEjr1zCsicMWpAA",
  "token_type":"example",
  "expires_in":3600,
  "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
  "example_parameter":"example_value"
}

客户端必须忽略无法识别的响应参数。令牌大小和从授权服务器接收到的值的大小未定义。客户端应该避免对值的大小做假设。授权服务器应记录其发放的任何值的大小。

5.2. 错误响应

授权服务器使用 HTTP 400(错误请求)状态码(除非指定其他的)响应,在响应中包含下列参数:

  • error

    必需的。下列 ASCII[USASCII] 错误代码之一:

    • invalid_request

      请求缺少必需的参数、包含不支持的参数值(除了许可类型)、重复参数、包含多个凭据、采用多种客户端身份验证机制或其他不规范的格式。

    • invalid_client

      客户端身份验证失败(例如,未知的客户端,不包含客户端身份验证,或不支持的身份验证方法)。授权服务器可以返回 HTTP 401(未授权)状态码来指出支持的 HTTP 身份验证方案。如果客户端试图通过“Authorization”请求头进行身份验证,授权服务器必须响应 HTTP 401(未授权)状态码,并包含与客户端使用的身份验证方案匹配的“WWW-Authenticate”响应头。

    • invalid_grant

      提供的授权许可(如授权码、资源所有者凭据)或刷新令牌无效、过期、吊销、与在授权请求使用的重定向 URI 不匹配或被颁发给其他客户端。

    • unauthorized_client

      进行身份验证的客户端没有被授权使用这种授权许可类型。

    • unsupported_grant_type

      授权许可类型不被授权服务器支持。

    • invalid_scope

      请求的范围无效、未知的、格式不正确或超出资源所有者许可的范围。

    “error”参数的值不能包含集合 %x20-21 / %x23-5B / %x5D-7E 以外的字符。

  • error_description

    可选的。提供额外的人类可读的 ASCII[USASCII] 信息文本,用于协助客户端开发人员理解所发生的错误。“error_description”参数的值不能包含集合 %x20-21 / %x23-5B / %x5D-7E 以外的字符。

  • error_uri

    可选的。指向包含有关错误信息的人类可读的网页 URI,用于向客户端开发人员提供关于该错误的额外信息。

    “error_uri”参数值必须符合 URI 参考语法,因此不能包含集合 %x21 / %x23-5B / %x5D-7E 以外的字符。

这些参数使用 [RFC4627] 定义的“application/json”媒体类型包含在 HTTP 响应实体正文中。将每个参数添加到最高结构级别并序列化为 JavaScript 对象表示法(JSON)的结构。参数名称和字符串值作为 JSON 字符串类型包含。数值的值作为 JSON 数字类型包含。参数顺序无关且可以变化。

例如:

HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "error":"invalid_request"
}

6. 刷新访问令牌

若授权服务器给客户端颁发了刷新令牌,客户端通过使用按 附录 B “application/x-www-form-urlencoded”格式在 HTTP 请求实体正文中发送下列 UTF-8 字符编码的参数向令牌端点发起刷新请求:

  • grant_type

    必需的。值必须设置为“refresh_token”。

  • refresh_token

    必需的。颁发给客户端的刷新令牌。

  • scope

    可选的。如 3.3 节所述的访问请求的范围。请求的范围不能包含任何不是由资源所有者原始许可的范围,若省略,则被视为与资源所有者原始许可的范围相同。

因为刷新令牌通常是用于请求额外的访问令牌的持久凭证,刷新令牌绑定颁发的客户端。如果客户端类型是机密的或客户端被颁发了客户端凭据(或选定的其他身份验证要求),客户端必须如 3.2.1 节所述与授权服务器进行身份验证。

例如,客户端在传输层安全下发起如下 HTTP 请求(额外的换行仅用于显示目的):

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA

授权服务器必须:

  • 要求对机密客户端或任何已获得客户端凭据(或具有其他身份验证要求)的客户端进行客户端身份验证,

  • 如果包含客户端身份验证,则对客户端进行身份验证,并确保将刷新令牌颁发给经过身份验证的客户端,以及

  • 验证刷新令牌。

如果有效并获得授权,授权服务器会如第 5.1 节所述颁发访问令牌。 如果请求验证失败或无效,授权服务器将返回如第 5.2 节所述的错误响应。

授权服务器可以发布一个新的刷新令牌,在这种情况下,客户端必须丢弃旧的刷新令牌并用新的刷新令牌替换它。 授权服务器可以在向客户端发出新的刷新令牌后撤销旧的刷新令牌。 如果发布了新的刷新令牌,则刷新令牌范围必须与客户端在请求中包含的刷新令牌的范围相同。

7. 访问受保护资源

客户端通过向资源服务器提供访问令牌来访问受保护的资源。 资源服务器必须验证访问令牌并确保它没有过期并且其范围涵盖了所请求的资源。 资源服务器用于验证访问令牌(以及任何错误响应)的方法超出了本规范的范围,但通常涉及资源服务器和授权服务器之间的交互或协调。

客户端使用访问令牌与资源服务器进行身份验证的方法取决于授权服务器颁发的访问令牌的类型。 通常,它涉及使用 HTTP“Authorization”请求头字段 [RFC2617] 和由所使用的访问令牌类型规范定义的身份验证方案,例如 [RFC6750]。

7.1. 访问令牌类型

访问令牌类型给客户端提供了成功使用该访问令牌(以及特定于类型的属性)发起受保护资源请求所需的信息。若客户端不理解令牌类型,则不能使用该访问令牌。

例如,[RFC6750] 中定义的“bearer”令牌类型通过简单地在请求中包含访问令牌字符串来使用::

GET /resource/1 HTTP/1.1
Host: example.com
Authorization: Bearer F_9.B5f-4.1JqM

而在 [OAuth-HTTP-MAC] 中定义的“mac”令牌类型通过发布消息验证码 (MAC) 密钥与用于签名某些 HTTP 请求的组件一起使用:

GET /resource/1 HTTP/1.1
Host: example.com
Authorization: MAC id="h480djs93hd8",nonce="274312:dj83hs9s",mac="kDZvddkndxvhGRXZhvuDjEWhGeE="

提供上面的例子仅作说明用途。建议开发人员在使用前查阅 [RFC6750] 和 [OAuth-HTTP-MAC] 规范。

每一种访问令牌类型的定义指定了与“access_token”响应参数一起发送到客户端的额外属性。它还定义了用于在发出受保护资源请求时包含访问令牌的 HTTP 身份验证方法。

7.2. 错误响应

如果资源访问请求失败,资源服务器应该通知客户端该错误。虽然此类错误响应的细节超出了本规范的范围,但本文档在第 11.4 节中建立了一个公共注册表,用于在 OAuth 令牌身份验证方案之间共用错误值。

主要为 OAuth 令牌身份认证设计的新认证方案应该定义一种机制,用于向客户端提供错误状态代码,其中允许的错误值注册在本规范建立的错误注册表中。

此类方案可以将有效错误代码集限制为注册值的子集。 如果使用命名参数返回错误代码,则参数名称应为“error”。

其他能够用于 OAuth 令牌身份验证的方案,即使其不是专门为此目的而设计的,也可以以相同的方式将它们的错误值绑定到注册表。

新的身份验证方案也可以选择指定使用“error_description”和“error_uri”参数,以与本规范中相同的方式返回错误信息。

8. 可扩展性

8.1. 定义访问令牌类型

访问令牌类型可以通过以下两种方式之一定义:在访问令牌类型注册表中注册(遵循 11.1 节中的过程),或者使用唯一的绝对 URI 作为其名称。

采用 URI 命名的类型应该限定于特定供应商的实现,它们不是普遍适用的并且特定于使用它们的资源服务器的实现细节。

所有其他类型都必须注册。类型名称必需符合 type-name ANBF。如果类型定义包含了一种新的 HTTP 身份验证方案,该类型名称应该与该 HTTP 身份验证方案名称一致(如 [RFC2617] 的定义)。令牌类型“example”被保留用于样例中。

type-name  = 1*name-char
name-char  = "-" / "." / "_" / DIGIT / ALPHA

8.2. 定义新的端点参数

用于授权端点或令牌端点的新的请求或响应参数按照 11.2 节中的过程在 OAuth 参数注册表中定义和注册。

参数名称必须符合 param-name ABNF,并且参数值的语法必须是明确定义的(例如,使用 ABNF,或现有参数的语法的引用)。

param-name  = 1*name-char
name-char   = "-" / "." / "_" / DIGIT / ALPHA

未注册的特定于供应商的扩展参数通常不适用,它们特定于使用它们的授权服务器的实现细节,应该使用不太可能与其他注册值冲突的供应商特定前缀(例如,以’companyname_‘开头)。

8.3. 定义新的授权许可类型

可以通过为它们分配一个唯一的绝对 URI 以与“grant_type”参数一起使用来定义新的授权许可类型。 如果扩展授权类型需要额外的令牌端点参数,它们必须如第 11.2 节所述在 OAuth 参数注册表中注册。

8.4. 定义新的授权端点响应类型

按照第 11.3 节中的过程,在授权端点响应类型注册表中定义和注册与授权端点一起使用的新响应类型。 响应类型名称必须符合 response-type ABNF。

response-type  = response-name *( SP response-name )
response-name  = 1*response-char
response-char  = "_" / DIGIT / ALPHA

如果响应类型包含一个或多个空格字符 (%x20),则将其作为以空格分隔的值列表进行比较,其中值的顺序无关紧要。只能注册一个值的顺序,它涵盖了同一组值的所有其他排列。

例如,响应类型“token code”未由本规范定义。然而,一个扩展可以定义和注册“token code”响应类型。 一旦注册,相同的组合“code token”便不能被注册,但是这两个值都可以用于表示相同的响应类型。

8.5. 定义其他错误代码

在协议扩展(例如,访问令牌类型、扩展参数或扩展许可类型等)需要其他错误码用于授权码许可错误响应( 4.1.2.1 节)、隐式授权错误响应( 4.2.2.1 节)、令牌错误响应( 5.2 节)或资源访问错误响应( 7.2 节)的情况下,这些错误代码可以被定义。

如果与它们一起使用的扩展是已注册的访问令牌类型、已注册的端点参数或扩展许可类型,则必须注册扩展错误代码(遵循第 11.4 节中的过程)。可以注册用于未注册扩展的错误代码。

错误代码必须符合 error ABNF,且可能的话应该以一致的名称作前缀。例如,给扩展参数“example”设置了无效值的错误应该被命名为“example_invalid”。

 error      = 1*error-char
 error-char = %x20-21 / %x23-5B / %x5D-7E

9. 本机应用程序

本机应用程序是安装和执行在资源所有者使用的设备上的客户端(例如,桌面程序,本机移动应用)。本机应用程序需要对安全、平台能力和整体最终用户体验特殊考虑。

授权端点需要在客户端和资源所有者用户代理之间进行交互。本机应用程序可以调用外部的用户代理,或在应用程序中嵌入用户代理。例如:

  • 外部用户代理——本机应用程序可以捕获来自授权服务器的响应。它可以使用操作系统已注册方案来调用客户端作为处理程序,手动复制粘贴凭据,运行本地 Web 服务器,安装用户代理扩展,或者通过提供重定向 URI 来指定客户端控制下的服务器托管资源,这反过来使响应可用于本机应用程序。

  • 嵌入式用户代理——本机应用程序通过监视资源加载期间发出的状态更改或访问用户代理的 cookie 存储直接与嵌入式用户代理通信来获取响应。

当在外部或嵌入式用户代理中选择时,开发者应该考虑如下:

  • 外部用户代理可能会提高完成率,因为资源所有者可能已经有了与授权服务器的活动会话,避免了重新进行身份验证的需要。它提供了熟悉的最终用户体验和功能。资源所有者可能也依赖于用户代理的功能或扩展帮助他进行身份验证(例如密码管理器、双因子验证器)

  • 嵌入式用户代理可能会提供更好的可用性,因为它避免了切换上下文和打开新窗口的需要。

  • 嵌入式用户代理构成了安全挑战,因为资源所有者在一个未知的窗口中进行身份验证,无法获得在大多数外部用户代理中的视觉体验保护。嵌入式用户代理要求用户信任未标识身份的验证请求(使钓鱼攻击更易于实施)。

当在隐式授权类型和授权码许可类型中选择时,下列应该被考虑:

  • 由于本机应用程序无法对客户端凭据保密,因此使用授权代码授权类型的本机应用程序应该在不使用客户端凭据的情况下这样做。

  • 当使用隐式授权类型流程时,不会返回刷新令牌,这就要求一旦访问令牌过期就要重复授权过程。

10. 安全考量

作为一个灵活可扩展的框架,OAuth 的安全性考量依赖于许多因素。 以下小节提为实现者提供了如 2.1 节所述的三种客户端配置上的安全指南:Web 应用、基于用户代理的应用和本地应用程序。

全面的 OAuth 安全模型和分析以及该协议设计的背景在 [OAuth-THREATMODE] 中提供。

10.1. 客户端身份验证

授权服务器与 Web 应用程序客户端建立客户端凭据以进行客户端身份验证。 鼓励授权服务器考虑比客户端密码更强的客户端身份验证方式。Web 应用程序客户端必须确保客户端密码和其他客户端凭据的机密性。

授权服务器不得出于客户端身份验证的目的向本地应用程序或基于用户代理的应用程序客户端颁发客户端密码或其他客户端凭据。授权服务器可以为专用设备上的本地应用程序客户端的特定安装发布客户端密码或其他凭据。

当客户端身份验证不可用时,授权服务器应该采用其他方式来验证客户端的身份-例如,通过要求客户端重定向 URI 的注册或者引入资源所有者来确认身份。当请求资源所有者授权时,有效的重定向 URI 是不足以验证客户端的身份,但可以用来防止在获得资源所有者授权后将凭据传递给假冒的客户端。

授权服务器必须考虑与未进行身份验证的客户端交互的安全实现,并采取措施限制颁发给这些客户端的其他凭据(如刷新令牌)的潜在泄露。

10.2. 客户端仿冒

如果被冒充的客户端未能或无法对其客户端凭据保密,则恶意客户端可以冒充另一个客户端并获得对受保护资源的访问权限。

授权服务器必须尽可能对客户端进行身份验证。如果授权服务器由于客户端的性质而无法对客户端进行身份验证,则授权服务器必须要求注册任何用于接收授权响应的重定向 URI,并且应该使用其他方式来保护资源所有者免受此类潜在恶意客户端的侵害。例如,授权服务器可以引入资源所有者来帮助识别客户端及其来源。

授权服务器应该实施显式的资源所有者身份验证并且告知资源所有者有关客户端及其请求的授权范围和生命周期。由资源所有者在当前客户端上下文中审查信息并授权或拒绝请求。

授权服务器不应该自动处理重复的授权请求(没有显示地与资源所有者交互)而不验证客户端或依赖其他措施来确保重复的请求来自原始客户端而不是伪造客户端。

10.3. 访问令牌

访问令牌凭据(以及任何机密的访问令牌属性)在传输和储存时必须保持机密性,并只与授权服务器、访问令牌生效的资源服务器和访问令牌被颁发的客户端共享。访问令牌凭据必须只能用 1.6 节所述的 TLS 与 [RFC2818] 定义授权服务器进行传输。

当使用隐式授权许可类型时,访问令牌在 URI 片段中传输,这可能泄露访问令牌给未授权的一方。

授权服务器必须确保访问令牌不能被未经授权方生成、修改或猜测以产生有效的访问令牌。

客户端应该以最小需求范围请求访问令牌。授权服务器在选择如何兑现请求的范围时应该将客户端身份考虑在内,且可以颁发具有比请求权限更小的访问令牌。

本规范没有为资源服务器提供任何方法来确保特定客户端提供给它的访问令牌是由授权服务器颁发给该客户端的。

10.4. 刷新令牌

授权服务器可以给 Web 应用客户端和本机应用程序客户端颁发刷新令牌。

刷新令牌在传输和储存时必须保持机密性,并只与授权服务器和刷新令牌被颁发的客户端共享。授权服务器必须维护刷新令牌和颁发的客户端之间的绑定信息。访问令牌凭据必须只能用 1.6 节所述的 TLS 与 [RFC2818] 定义授权服务器进行传输。

每当可以验证客户端身份时,授权服务器必须验证刷新令牌和客户端身份之间的绑定。当客户端身份验证不可行时,授权服务器应该部署其他方法来检测刷新令牌是否被滥用。

例如,授权服务器可以使用刷新令牌轮换机制,随着每次访问令牌刷新响应,新的刷新令牌被颁发。旧的刷新令牌作废但是由授权服务器保留。如果刷新令牌被泄露,随后同时被攻击者和合法客户端使用,他们中一人将提交被作废的刷新令牌,该入侵将通知给授权服务器。

授权服务器必须确保刷新令牌不能被未经授权方生成、修改或猜测以产生有效的访问令牌。

10.5. 授权码

授权码的传输应该建立在安全通道上,如果重定向 URI 指向了一个网络资源,那么客户端应该要求使用 TLS。由于授权码由用户代理重定向传输,它们可能潜在地通过用户代理历史记录和 HTTP referrer 请求头被泄露。

授权码作为文本形式的凭据,用于验证在授权服务器给予授权许可和返回授权许可给客户端以完成授权过程的是同一资源所有者。因此,如果客户端依赖于授权码作为它自己的资源所有者身份验证,客户端重定向端点必须要求使用 TLS。

授权码必须是短暂及单用户的。如果授权服务器观察到多次用授权码交换访问令牌的尝试,授权服务器应该试图吊销所有基于泄露的授权码颁发的访问令牌。

如果客户端可以进行身份验证,授权服务器必须验证客户端身份,并确该保授权码颁发给了此客户端。

10.6. 授权码重定向 URI 伪造

当使用授权码许可类型请求授权时,客户端可以通过“redirect_uri”参数指定重定向 URI。 如果攻击者能够伪造重定向 URI 的值,这可能导致授权服务器重定向资源所有者的用户代理到攻击者控制的 URI,同时将授权码加入到 URI 中。

攻击者可以在合法客户端上创建一个帐户,并开始授权流程。当攻击者的用户代理被发送到授权服务器授予访问权限时,攻击者会抓取合法客户端提供的授权 URI,并将客户端的重定向 URI 替换为攻击者控制下的 URI。攻击者然后诱使受害者跟随被操纵的链接以授权访问合法客户端。

一旦到达授权服务器后,受害者会被提示代表合法且受信任的客户端发出正常、有效的请求,并授权该请求。然后,受害者带着授权码重定向到受攻击者控制的端点。攻击者通过使用客户端提供的原始重定向 URI 向客户端发送授权码来完成授权流程。客户端用授权码交换访问令牌并与将它与攻击者的客户端账号关联,然后,该账户现在能获得受害者授权的(通过客户端)对访问受保护资源的访问权限。

为了防止这种攻击,授权服务器必须确保用于获得授权码的重定向 URI 与用授权码交换访问令牌时提供的重定向 URI 相同。授权服务器必须要求公共客户端,并且应该要求机密客户注册它们的重定向 URI。如果请求中提供了重定向 URI,授权服务器必须根据注册值对其进行验证。

10.7. 资源所有者密码凭据

资源所有者密码凭据许可类型通常用于遗留或迁移原因。它降低了由客户端存储用户名和密码的整体风险,但并没有消除泄露高度特权的凭证给客户端的需求。

这种许可类型比其他许可类型承载了更高的风险,因为它保留了本协议寻求避免密码的反模式。客户端可能滥用密码或密码可能会无意中被泄露给攻击者(例如,通过客户端保存的日志文件或其他记录)。

此外,由于资源所有者无法控制授权过程(资源所有者的参与在将其凭据移交给客户端时结束),因此客户端可以获得比资源所有者预期的具有更大范围的访问令牌。授权服务器应该考虑由这种许可类型颁发的访问令牌的范围和生命周期。

授权服务器和客户端应该尽量减少这种许可类型的使用,并尽可能采用其他许可类型。

10.8. 请求机密性

访问令牌、刷新令牌、资源所有者密码和客户端凭据不得以明文形式传输。授权代码不应以明文形式传输。

“state”和“scope”参数不应该包含敏感的客户端或资源所有者的纯文本信息,因为它们可能在不安全的通道上被传输或被不安全地存储。

10.9. 确保端点真实性

为了防止中间人攻击,对于发送到授权和令牌端点的任何请求,授权服务器必须要求使用 TLS 和 [RFC2818] 定义的服务器身份验证。客户端必须按照 [RFC6125] 的定义并根据其对服务器身份验证的要求来验证授权服务器的 TLS 证书。

10.10. 凭据猜测攻击

授权服务器必须防止攻击者猜测访问令牌、授权码、刷新令牌、资源所有者密码和客户端凭据。

攻击者猜测已生成令牌(和其它不打算被最终用户掌握的凭据)的概率必须小于或等于 2 ^(-128),并且应该小于或等于 2 ^(-160)。

授权服务器必须使用其他方式来保护旨在供最终用户使用的凭据。

10.11. 钓鱼攻击

此协议和类似协议的广泛部署可能会导致最终用户习惯于被重定向到要求他们输入密码的网站的做法。如果最终用户在输入凭据之前不认真地验证这些网站的真实性,攻击者就有可能利用这种做法窃取资源所有者的密码。

服务提供商应尝试向最终用户宣传网络钓鱼攻击所带来的风险,并应提供使最终用户能够轻松确认其网站真实性的机制。客户端开发人员应该考虑他们如何与用户代理(例如,外部、嵌入式)交互的安全含义,以及最终用户验证授权服务器真实性的能力。

为了降低网络钓鱼攻击的风险,授权服务器必须要求在用于最终用户交互的每个端点上使用 TLS。

10.12. 跨站请求伪造

跨站点请求伪造 (CSRF) 是一种漏洞,攻击者利用此漏洞使受害最终用户的用户代理将恶意 URI(例如,作为误导性链接、图像或重定向提供给用户代理)跟踪到信任服务器(通常通过有效会话 cookie 的存在建立)。

针对客户端的重定向 URI 的 CSRF 攻击允许攻击者注入自己的授权码或访问令牌,这将导致在客户端中使用与攻击者的受保护资源关联的访问令牌而非受害者的(例如,将受害者的银行账户信息保存到攻击者控制的受保护资源上)。

客户端必须为它的重定向 URI 实现 CSRF 保护。这通常通过要求向重定向 URI 端点发送的任何请求包含一个与用户代理身份认证状态绑定的值(例如,用于对用户代理进行身份验证的会话 Cookie 的哈希值)来实现。客户端应该使用“state”请求参数在发起授权请求时向授权服务器传送该值。

一旦从最终用户获得授权,授权服务器将最终用户的用户代理重定向回客户端,并在“state”参数中包含所需的绑定值。绑定值使客户端能够通过将绑定值与用户代理的身份验证状态对比来验证请求的有效性。用于 CSRF 保护的绑定值必须包含不可猜测的值(如 10.10 节所述)且用户代理的身份验证状态(例如会话 Cookie、HTML5 本地存储)必须保存在只能被客户端和用户代理访问的地方(即受同源策略保护)。

针对授权服务器的授权端点的 CSRF 攻击可能导致攻击者在不涉及或警告最终用户的情况下获得恶意客户端的最终用户授权。

授权服务器必须为它的授权端点实现 CSRF 保护并且确保在资源所有者未意识到且无显式同意时恶意客户端不能获得授权

授权服务器必须为其授权端点实施 CSRF 保护,并确保恶意客户端在没有资源所有者的察觉和明确同意的情况下无法获得授权。

10.13. 点击劫持

在点击劫持攻击中,攻击者注册一个合法客户端,然后构建一个恶意站点,在该站点中,它将授权服务器的授权端点网页加载到覆盖在一组虚拟按钮之上的透明 iframe 中,这些虚拟按钮经过精心构造,可以直接放置在授权页面的重要按钮下。当最终用户单击一个误导性的可见按钮时,最终用户实际上是在单击授权页面上的一个不可见按钮(例如“授权”按钮)。这允许攻击者在最终用户不知情的情况下诱骗资源所有者授予其客户端访问权限。

为了防止这种形式的攻击,本机应用程序在请求最终用户授权时应该使用外部浏览器而不是在应用程序中嵌入浏览器。对于大多数较新的浏览器,授权服务器可以使用(非标准)“x-frame-options”标头强制避免 iframe。这个标头可以有两个值,“deny”和“sameorigin”,它们将分别阻止任何框架,或由具有不同来源的站点组成的框架。对于较旧的浏览器,可以使用 JavaScript 框架破坏技术,但可能并非在所有浏览器中都有效。

10.14. 代码注入和输入验证

当输入或其他外部变量被未经过滤的应用程序使用并导致对应用程序逻辑的修改时,就会发生代码注入攻击。这可能允许攻击者访问应用程序设备或其数据,导致拒绝服务,或引入广泛的恶意副作用。

授权服务器和客户端必须过滤(并在可能的情况下验证)收到的任何值——特别是,“state”和“redirect_uri”参数的值。

10.15. 自由重定向器

授权服务器、授权端点和客户端重定向端点可能被不当配置,被作为自由重定向器。自由重定向器是一个使用参数自动地向参数值指定而无任何验证的地址重定向用户代理的端点。

自由重定向器可被用于钓鱼攻击,或者被攻击者通过使用熟悉的受信任的目标地址的 URI 授权部分使最终用户访问恶意站点。此外,如果授权服务器允许客户端只注册部分的重定向 URI,攻击者可以使用客户端操作的自由重定向器构造重定向 URI,该 URI 将通过授权服务器验证,但会发送授权码或访问令牌到攻击者控制下的端点。

10.16. 在隐式授权流程中滥用访问令牌假冒资源所有者

对于使用隐式授权流程的公共客户端,本规范没有为客户端提供任何方法来决定访问令牌颁发给的是哪个的客户端。

资源所有者可能通过给攻击者的恶意客户端许可访问令牌来自愿委托对资源的访问。这可能是由于钓鱼或一些其他借口。攻击者也可能通过其他机制窃取令牌。然后,攻击者可能会尝试通过向合法公开客户端提供该访问令牌假冒资源拥有者。

在隐式流程(response_type=token)中,攻击者可以轻易切换来自授权服务器的响应中的令牌,用事先颁发给攻击者的令牌替换真实的访问令牌。

与本机应用程序通信的服务器依赖于在后台通道中传递一个访问令牌来识别客户端用户,攻击者创建一个可以注入任意被盗访问令牌的受攻击应用程序,可能会对这些服务器造成类似的威胁。

任何假设只有资源所有者才能向其提供资源的有效访问令牌的公共客户端都容易受到此类攻击。

这种类型的攻击可能会将合法客户端的资源所有者信息暴露给攻击者(恶意客户端)。这也将允许攻击者以与最初授予访问令牌或授权代码的资源所有者相同的权限在合法客户端执行操作。

客户端对资源拥有者进行身份验证超出了本规范的范围。任何使用授权过程作为客户端对受委托的最终用户进行身份验证的形式的规范(例如,第三方登录服务)不得在没有额外的安全机制的情况下使用隐式流程,这些安全机制使客户端能够确定是否访问颁发令牌供其使用(例如,限制访问令牌的受众)。

11. IANA 考量

11.1. OAuth 访问令牌类型注册表

本规范建立 OAuth 访问令牌类型注册表。

[email protected] 邮件列表上经过两周的审查期且在一个或多个指定专家的建议下,以规范要求([RFC5226])注册访问令牌类型。但是,为了允许在发布之前分配值,指定专家可以在他们对将发布的规范感到满意后批准注册。

注册请求必须发送到 [email protected] 邮件列表进行审查和评论,并附上适当的主题(例如,“Request for access token type: example”)。

在审查期内,指定专家(们)将批准或拒绝注册请求,并将此决定传达给审核名单和 IANA。 拒绝应包括解释,如果可能的话,还应包括有关如何修正请求的建议。

IANA 必须只接受指定专家(们)的注册更新,并应将所有注册请求发送至审核邮件列表。

11.1.1. 注册模板

  • Type name:

    请求的名称(例如,“example”)。

  • Additional Token Endpoint Response Parameters:

    与“access_token”参数一起返回的附加响应参数。 如第 11.2 节所述,新参数必须在 OAuth 参数注册表中单独注册。

  • HTTP Authentication Scheme(s):

    HTTP 身份验证方案名称(如果有),用于使用此类型的访问令牌对受保护的资源请求进行身份验证。

  • Change controller:

    对于标准过程的 RFC,请注明“IETF”。 对于其他人,请提供责任方的名称。 还可能包括其他详细信息(例如,邮政地址、电子邮件地址、主页 URI)。

  • Specification document(s):

    指定参数的文档的引用文献,最好包括可以用于检索文档副本的 URI。 也可以包括相关章节的说明,但不是必需的。

11.2. OAuth 参数注册表

本规范建立 OAuth 参数注册表。

授权端点请求、授权端点响应、令牌端点请求和令牌端点响应中包含的其他参数在 [email protected] 邮件列表上经过两周审查后,根据一名或多名指定专家的建议,按照所需规范([RFC5226])注册。但是,为了允许在发布之前分配值,指定专家可以在他们对将发布的规范感到满意后批准注册。

注册请求必须发送到 [email protected] 邮件列表进行审查和评论,并附上适当的主题(例如,“Request for parameter: example”)。

在审查期间,指定的专家(们)将批准或拒绝注册请求,并将此决定传达给审核名单和 IANA。拒绝应包括解释,如果可能的话,还应包括有关如何修正请求的建议。

IANA 必须只接受指定专家(们)的注册更新,并应将所有注册请求发送至审核邮件列表。

11.2.1. 注册模板

  • Parameter name:

    请求的名称(例如,“example”)。

  • Parameter usage location:

    参数可以使用的位置。可能的位置为授权请求、授权响应、令牌请求或令牌响应。

  • Change controller:

    对于标准化过程的 RFC,指定为“IETF”。对于其他人,请提供责任方的名称。 还可能包括其他详细信息(例如,邮政地址、电子邮件地址、主页 URI)。

  • Specification document(s):

    指定参数的文档的引用文献,最好包括可以用于检索文档副本的 URI。 也可以包括相关章节的说明,但不是必需的。

11.2.2. 初始的注册表内容

OAuth 参数注册表中的初始内容:

  • Parameter name: client_id
  • Parameter usage location: authorization request, token request
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: client_secret
  • Parameter usage location: token request
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: response_type
  • Parameter usage location: authorization request
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: redirect_uri
  • Parameter usage location: authorization request, token request
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: scope
  • Parameter usage location: authorization request, authorization response, token request, token response
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: state
  • Parameter usage location: authorization request, authorization response
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: code
  • Parameter usage location: authorization response, token request
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: error_description
  • Parameter usage location: authorization response, token response
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: error_uri
  • Parameter usage location: authorization response, token response
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: grant_type
  • Parameter usage location: token request
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: access_token
  • Parameter usage location: authorization response, token response
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: token_type
  • Parameter usage location: authorization response, token response
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: expires_in
  • Parameter usage location: authorization response, token response
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: username
  • Parameter usage location: token request
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: password
  • Parameter usage location: token request
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Parameter name: refresh_token
  • Parameter usage location: token request, token response
  • Change controller: IETF
  • Specification document(s): RFC 6749

11.3. OAuth 授权端点响应类型注册表

本规范建立 OAuth 授权端点响应类型注册表。

用于授权端点的其他响应类型在 [email protected] 邮件列表上经过两周审查后,根据一名或多名指定专家的建议,按照所需规范([RFC5226])注册。但是,为了允许在发布之前分配值,指定专家可以在他们对将发布的规范感到满意后批准注册。

注册请求必须发送到 [email protected] 邮件列表进行审查和评论,并附上适当的主题(例如,“Request for parameter: example”)。

在审查期间,指定的专家(们)将批准或拒绝注册请求,并将此决定传达给审核名单和 IANA。拒绝应包括解释,如果可能的话,还应包括有关如何修正请求的建议。

IANA 必须只接受指定专家(们)的注册更新,并应将所有注册请求发送至审核邮件列表。

11.3.1. 注册模板

  • Response type name:

    请求的名称(例如,“example”)。

  • Change controller:

    对于标准化过程的 RFC,指定为“IETF”。对于其他人,请提供责任方的名称。 还可能包括其他详细信息(例如,邮政地址、电子邮件地址、主页 URI)。

  • Specification document(s):

    指定参数的文档的引用文献,最好包括可以用于检索文档副本的 URI。 也可以包括相关章节的说明,但不是必需的。

11.3.2. 初始的注册表内容

OAuth 授权端点响应类型注册表的初始内容:

  • Response type name: code
  • Change controller: IETF
  • Specification document(s): RFC 6749

.

  • Response type name: token
  • Change controller: IETF
  • Specification document(s): RFC 6749

11.4. OAuth 扩展错误注册表

本规范建立 OAuth 扩展错误注册表。

与其他协议扩展一起使用的附加错误代码(即扩展授权类型、访问令牌类型或扩展参数)在 [email protected] 邮件列表上经过两周审查后,根据一名或多名指定专家的建议,按照所需规范([RFC5226])注册。但是,为了允许在发布之前分配值,指定专家可以在他们对将发布的规范感到满意后批准注册。

注册请求必须发送到 [email protected] 邮件列表进行审查和评论,并附上适当的主题(例如,“Request for parameter: example”)。

在审查期间,指定的专家(们)将批准或拒绝注册请求,并将此决定传达给审核名单和 IANA。拒绝应包括解释,如果可能的话,还应包括有关如何修正请求的建议。

IANA 必须只接受指定专家(们)的注册更新,并应将所有注册请求发送至审核邮件列表。

11.4.1. 注册模板

  • Error name:

    请求的名称(例如,“example”)。错误名称的值不能包含集合 %x20-21 / %x23-5B / %x5D-7E 以外的字符。

  • Error usage location:

    错误使用的位置。可能的位置是授权代码许可错误响应( 4.1.2.1 节),隐式授权错误响应( 4.2.2.1 节),令牌错误响应( 5.2 节),或资源访问错误的响应( 7.2 节)。

  • Related protocol extension:

    与错误代码一起使用的扩展许可类型、访问令牌类型或扩展参数的名称。

  • Change controller:

    对于标准化过程的 RFC,指定为“IETF”。对于其他人,请提供责任方的名称。 还可能包括其他详细信息(例如,邮政地址、电子邮件地址、主页 URI)。

  • Specification document(s):

    指定参数的文档的引用文献,最好包括可以用于检索文档副本的 URI。 也可以包括相关章节的说明,但不是必需的。

12. 参考文献

12.1. 规范性参考文件

  • [RFC2119]

    Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels”, BCP 14,RFC 2119, March 1997.

  • [RFC2246]

    Dierks, T. and C. Allen, “The TLS Protocol Version 1.0”, RFC 2246, January 1999.

  • [RFC2616]

    Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, “Hypertext Transfer Protocol – HTTP/1.1”, RFC 2616, June 1999.

  • [RFC2617]

    Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., Leach, P., Luotonen, A., and L. Stewart, “HTTP Authentication: Basic and Digest Access Authentication”, RFC 2617, June 1999.

  • [RFC2818]

    Rescorla, E., “HTTP Over TLS”, RFC 2818, May 2000.

  • [RFC3629]

    Yergeau, F., “UTF-8, a transformation format of ISO 10646”, STD 63, RFC 3629, November 2003.

  • [RFC3986]

    Berners-Lee, T., Fielding, R., and L. Masinter, “Uniform Resource Identifier (URI): Generic Syntax”, STD 66, RFC 3986, January 2005.

  • [RFC4627]

    Crockford, D., “The application/json Media Type for JavaScript Object Notation (JSON)”, RFC 4627, July 2006.

  • [RFC4949]

    Shirey, R., “Internet Security Glossary, Version 2”, RFC 4949, August 2007.

  • [RFC5226]

    Narten, T. and H. Alvestrand, “Guidelines for Writing an IANA Considerations Section in RFCs”, BCP 26,RFC 5226, May 2008.

  • [RFC5234]

    Crocker, D. and P. Overell, “Augmented BNF for Syntax Specifications: ABNF”, STD 68, RFC 5234, January 2008.

  • [RFC5246]

    Dierks, T. and E. Rescorla, “The Transport Layer Security (TLS) Protocol Version 1.2”, RFC 5246, August 2008.

  • [RFC6125]

    Saint-Andre, P. and J. Hodges, “Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS)”, RFC 6125, March 2011.

  • [USASCII]

    American National Standards Institute, “Coded Character Set – 7-bit American Standard Code for Information Interchange”, ANSI X3.4, 1986.

  • [W3C.REC-html401-19991224]

    Raggett, D., Le Hors, A., and I. Jacobs, “HTML 4.01 Specification”, World Wide Web Consortium Recommendation REC-html401-19991224, December 1999, http://www.w3.org/TR/1999/REC-html401-19991224.

  • [W3C.REC-xml-20081126]

    Bray, T., Paoli, J., Sperberg-McQueen, C., Maler, E., and F. Yergeau, “Extensible Markup Language (XML) 1.0 (Fifth Edition)”, World Wide Web Consortium Recommendation REC-xml-20081126, November 2008, http://www.w3.org/TR/2008/REC-xml-20081126.

12.2. 参考性引用文献

  • [OAuth-HTTP-MAC]

    Hammer-Lahav, E., Ed., “HTTP Authentication: MAC Access Authentication”, Work in Progress, February 2012.

  • [OAuth-SAML2]

    Campbell, B. and C. Mortimore, “SAML 2.0 Bearer Assertion Profiles for OAuth 2.0”, Work in Progress, September 2012.

  • [OAuth-THREATMODEL]

    Lodderstedt, T., Ed., McGloin, M., and P. Hunt, “OAuth 2.0 Threat Model and Security Considerations”, Work in Progress, October 2012.

  • [OAuth-WRAP]

    Hardt, D., Ed., Tom, A., Eaton, B., and Y. Goland, “OAuth Web Resource Authorization Profiles”, Work in Progress, January 2010.

  • [RFC5849]

    Hammer-Lahav, E., “The OAuth 1.0 Protocol”, RFC 5849, April 2010.

  • [RFC6750]

    Jones, M. and D. Hardt, “The OAuth 2.0 Authorization Framework: Bearer Token Usage”, RFC 6750, October 2012.

附录 A. 扩充巴库斯-瑙尔形式 (ABNF) 语法

本节使用 [RFC5234] 的表示法为本规范中定义的元素提供扩充巴科斯-瑙尔形式 (ABNF) 语法描述。下面的 ABNF 是根据 Unicode 代码点 [W3C.REC-xml-20081126] 定义的;这些字符通常以 UTF-8 编码。元素按首先定义的顺序呈现。

下面的一些定义使用 [RFC3986] 中的“URI-reference”定义。

下面的一些定义使用这些通用定义:

VSCHAR  = %x20-7E
NQCHAR  = %x21 / %x23-5B / %x5D-7E
NQSCHAR = %x20-21 / %x23-5B / %x5D-7E
UNICODECHARNOCRLF = %x09 /%x20-7E / %x80-D7FF / %xE000-FFFD / %x10000-10FFFF

(UNICODECHARNOCRLF 定义基于 [W3C.REC-xml-20081126] 第 2.2 节中的 Char 定义,但省略了回车符和换行符。)

A.1. “client_id” 语法

“client_id” 元素在 2.3.1 节定义:

client-id =*VSCHAR

A.2. “client_secret” 语法

“client_secret” 元素在 2.3.1 节定义:

client-secret = *VSCHAR

A.3. “response_type” 语法

“response_type” 元素在 3.1.1 和 8.4 节定义:

response-type = response-name*( SP response-name )
response-name = 1*response-char
response-char = "_" / DIGIT / ALPHA

A.4. “scope” 语法

“scope” 元素在 3.3 节定义:

scope       = scope-token *( SP scope-token )
scope-token = 1*NQCHAR

A.5. “state” 语法

“state” 元素在 4.1.1, 4.1.2, 4.1.2.1, 4.2.1, 4.2.2, 和 4.2.2.1 节定义:

state = 1*VSCHAR

A.6. “redirect_uri” 语法

“redirect_uri” 元素在 4.1.1, 4.1.3, 和 4.2.1 节定义:

redirect-uri = URI-reference

A.7. “error” 语法

“error” 元素在 4.1.2.1, 4.2.2.1, 5.2, 7.2, 和 8.5 节定义:

error = 1*NQSCHAR

A.8. “error_description” 语法

“error_description” 元素在 4.1.2.1, 4.2.2.1, 5.2, 和 7.2 节定义:

error-description = 1*NQSCHAR

A.9. “error_uri” 语法

“error_uri” 元素在 4.1.2.1, 4.2.2.1, 5.2, 和 7.2 节定义:

error-uri = URI-reference

A.10. “grant_type” 语法

“grant_type” 元素在 4.1.3, 4.3.2, 4.4.2, 4.5, 和 6 节定义:

grant-type = grant-name / URI-reference
grant-name = 1*name-char
name-char = "-" / "." / "_" / DIGIT / ALPHA

A.11. “code” 语法

“code” 元素在 4.1.3 节定义:

code = 1*VSCHAR

A.12. “access_token” 语法

“access_token” 元素在 4.2.2 和 5.1 节定义:

access-token = 1*VSCHAR

A.13. “token_type” 语法

“token_type” 元素在 4.2.2, 5.1, 和 8.1 节定义:

token-type = type-name / URI-reference
type-name = 1*name-char
name-char = "-" / "." / "_" / DIGIT / ALPHA

A.14. “expires_in” 语法

“expires_in” 元素在 4.2.2 和 5.1 节定义:

expires-in = 1*DIGIT

A.15. “username” 语法

“username” 元素在 4.3.2 节定义:

username = *UNICODECHARNOCRLF

A.16. “password” 语法

“password” 元素在 4.3.2 节定义:

password =*UNICODECHARNOCRLF

A.17. “refresh_token” 语法

“refresh_token” 元素在 5.1 和 6 节定义:

refresh-token = 1*VSCHAR

A.18. Endpoint Parameter 语法

新端点参数的语法在 8.2 节定义:

param-name = 1*name-char
name-char = "-" / "." / "_" / DIGIT / ALPHA

附录 B. application/x-www-form-urlencoded 媒体类型的使用

在本规范发布时,“application/x-www-form-urlencoded”媒体类型在 [W3C.REC-html401-19991224] 的第 17.13.4 节中定义,但未在 IANA MIME 媒体类型注册表中注册 (http://www.iana.org/assignments/media-types)。 此外,该定义是不完整的,因为它没有考虑非 US-ASCII 字符。

为了在使用这种媒体类型生成有效负载时解决这个缺点,必须首先使用 UTF-8 字符编码方案 [RFC3629] 对名称和值进行编码; 然后需要使用 [W3C.REC-html401-19991224] 中定义的转义规则对生成的八位字节序列进行进一步编码。

当从使用这种媒体类型的有效载荷中解析数据时,由于转换名称/值编码而产生名称和值,因此需要被视为八位字节序列,以使用 UTF-8 字符编码方案进行解码。

例如,值中包含这六种 Unicode 编码点 (1) U+0020 (SPACE), (2) U+0025 (PERCENT SIGN), (3) U+0026 (AMPERSAND), (4) U+002B (PLUS SIGN), (5) U+00A3 (POUND SIGN), and (6) U+20AC (EURO SIGN) 将被编码到下面的八位字节序列中(使用十六进制表示法):

20 25 26 2B C2 A3 E2 82 AC

然后在有效载荷中表示为:

+%25%26%2B%C2%A3%E2%82%AC

附录 C. 致谢

最初的 OAuth 2.0 协议规范由 David Recordon 编辑,基于之前的两个出版物:OAuth 1.0 社区规范 [RFC5849] 和 OAuth WRAP(OAuth Web Resource Authorization Profiles)[OAuth-WRAP]。 然后,Eran Hammer 编辑了许多演变成该 RFC 的中间草案。 安全注意事项部分由 Torsten Lodderstedt、Mark McGloin、Phil Hunt、Anthony Nadalin 和 John Bradley 起草。 关于使用“application/x-www-form-urlencoded”媒体类型的部分由 Julian Reschke 起草。 ABNF 部分由 Michael B. Jones 起草。

OAuth 1.0 社区规范由 Eran Hammer 编辑并由 Mark Atwood、Dirk Balfanz、Darren Bounds、Richard M. Conlan、Blaine Cook、Leah Culver、Breno de Medeiros、Brian Eaton、Kellan Elliott-McCrea、Larry Halff、Eran Hammer、Ben Laurie、Chris Messina、John Panzer、Sam Quigley、David Recordon、Eran Sandler、Jonathan Sergent、Todd Sieling、Brian Slesinsky 和 Andy Smith 撰写。

OAuth WRAP 规范由 Dick Hardt 编辑,由 Brian Eaton、Yaron Y. Goland、Dick Hardt 和 Allen Tom 撰写。

该规范是 OAuth 工作组的工作,该工作组包括数十名积极和专注的参与者。特别是,以下个人提供了形成最终规范的想法、反馈和措辞:

Michael Adams、Amanda Anganes、Andrew Arnott、Dirk Balfanz、Aiden Bell、John Bradley、Marcos Caceres、Brian Campbell、Scott Cantor、Blaine Cook、Roger Crew、Leah Culver、Bill de hOra、Andre DeMarre、Brian Eaton、Wesley Eddy、Wolter Eldering、Brian Ellin、Igor Faynberg、George Fletcher、Tim Freeman、Luca Frosini、Evan Gilbert、Yaron Y. Goland、Brent Goldman、Kristoffer Gronowski、Eran Hammer、Dick Hardt、Justin Hart、Craig Heath、Phil Hunt、Michael B. Jones、Terry Jones、John Kemp、Mark Kent、Raffi Krikorian、Chasen Le Hara、Rasmus Lerdorf、Torsten Lodderstedt、Hui-Lan Lu、Casey Lucas、Paul Madsen、Alastair Mair、Eve Maler、James Manger、Mark McGloin、Laurence Miao、William Mills、Chuck Mortimore、Anthony Nadalin、Julian Reschke、Justin Richer、Peter Saint-Andre、Nat Sakimura、Rob Sayre、Marius Scurtescu、Naitik Shah、Luke Shepard、Vlad Skvortsov、Justin Smith、Haibin Song、Niv Steingarten、Christian Stuebner、Jeremy Suriel、Paul Tarjan、Christopher Thomas、Henry S. Thompson、Allen Tom、Franklin Tse、Nick Walker、Shane Weeden 和 Skylar Woodward。

本文件是在 Blaine Cook、Peter Saint-Andre、Hannes Tschofenig、Barry Leiba 和 Derek Atkins 的主持下编写的。 区域主管包括 Lisa Dusseault、Peter Saint-Andre 和 Stephen Farrell。

作者地址

Dick Hardt (editor) Microsoft EMail: [email protected] URI: http://dickhardt.org/