| 互联网草案 | OAuth 2.1 授权框架 | 2026 年 9 月 |
| Hardt 等人 | 2027 年 3 月 7 日到期 | [页] |
OAuth 2.1 授权框架使 应用程序能够获得对受保护资源的有限访问权限,可以 代表资源所有者,通过协调资源所有者 与授权服务之间的批准交互来实现,也可以允许 应用程序代表自身获得访问权限。此 规范取代并废止 RFC 6749 中描述的 OAuth 2.0 授权 框架以及 RFC 6750 中的持有者令牌用法。¶
此注释将在作为 RFC 发布之前删除。¶
有关本文档的讨论在 OAuth 工作组邮件列表(oauth@ietf.org)上进行, 其存档位于 https://mailarchive.ietf.org/arch/browse/oauth/。¶
此草案的源文件和问题跟踪器可在 https://github.com/oauth-wg/oauth-v2-1 找到。¶
本互联网草案的提交完全符合 BCP 78 和 BCP 79 的规定。¶
互联网草案是互联网工程任务组 (IETF)的工作文档。请注意,其他组织也可能将工作 文档作为互联网草案发布。当前互联网草案的列表 位于 https://datatracker.ietf.org/drafts/current/。¶
互联网草案是有效期最长为六个月的草案文档, 并且随时可能被其他文档更新、替代或废止。 不宜将互联网草案用作参考 材料,或以“进行中的工作”之外的方式引用它们。¶
本互联网草案将于 2027 年 3 月 7 日到期。¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
OAuth 通过将客户端的角色与资源 所有者的角色分离,为客户端-服务器认证模型引入了授权层。 在 OAuth 中,客户端请求访问由资源所有者控制并 托管在资源服务器上的资源。 客户端不使用资源所有者的凭据访问受保护的 资源,而是获取访问令牌——一种表示 一组特定访问属性(例如作用域和生命周期)的凭据。访问 令牌由授权服务器在获得资源所有者批准后颁发给客户端。 客户端使用访问令牌访问托管在资源服务器上的 受保护资源。¶
在较旧、功能更有限的客户端-服务器认证模型中,客户端 通过使用资源所有者的 凭据向服务器进行认证,来请求服务器上的受限访问资源 (受保护资源)。为了让应用程序能够访问 受限资源,资源所有者会与应用程序共享其凭据。 这会造成若干问题和限制:¶
应用程序需要存储资源 所有者的凭据以供将来使用,通常是以 明文形式存储密码。¶
服务器需要支持密码认证,尽管 密码本身存在固有的安全弱点。¶
应用程序会获得对资源 所有者受保护资源过于宽泛的访问权限,使资源所有者无法 限制访问持续时间,也无法将访问限制在 资源的有限子集内。¶
资源所有者经常会在其他无关 服务中重复使用密码,尽管最佳安全实践并不建议这样做。这种密码重复使用意味着 一个服务中的漏洞或泄露可能会对 完全无关的服务产生安全影响。¶
资源所有者无法撤销单个应用程序的访问权限 而不同时撤销所有第三方的访问权限,并且必须通过 更改密码来实现。¶
任何应用程序一旦被攻破,都会导致 最终用户的密码以及由该 密码保护的所有数据被泄露。¶
OAuth 的一个使用示例是:最终用户(资源所有者)授予某个财务 管理 服务(客户端)访问存储在银行服务(资源服务器)中的 敏感交易历史的权限,而无需与该财务管理服务共享其用户名和 密码。相反,用户直接向其金融机构的服务器 (授权服务器)进行认证, 该服务器会向财务管理服务颁发特定于委托的凭据 (访问令牌)。¶
这种关注点分离还使得能够使用更高级的 用户认证方法,例如多因素认证,甚至是 无密码认证,而无需对应用程序进行任何修改。 由于所有用户认证逻辑都由授权服务器处理, 应用程序无需关心实现 任何特定认证机制的具体细节。这使 授权服务器能够管理用户认证策略,并且 甚至可以在将来更改这些策略,而无需与应用程序协调这些更改。¶
授权层还可以简化资源服务器确定 请求是否已获授权的方式。传统上,在客户端完成认证后, 每个资源服务器都会评估策略,以计算客户端在每次 API 调用中是否被授权。 在分布式系统中,这些策略需要同步到 所有资源服务器,或者资源服务器必须调用中央策略 服务器来处理每个请求。在 OAuth 中,仅当授权服务器创建 新的访问令牌时才会评估策略。如果 已授权的访问权限体现在访问令牌中,资源服务器便不再 需要评估策略,而只需验证访问令牌。 无论应用程序是代表资源 所有者执行操作,还是代表自身执行操作,都适用这种简化方式。¶
OAuth 是一种授权协议,而不是认证协议,因为 OAuth 并未 定义实现用户认证所必需的组件。 如果目标是认证用户,则必须使用认证协议。一个示例是 OpenID Connect [OpenID.Connect],它构建于 OAuth 之上,以提供认证协议所需的安全 特性和必要组件。¶
访问令牌表示授予客户端的授权。客户端通常会 将访问令牌提交给专有 API,该 API 返回资源所有者的用户标识符,然后将该 API 的结果作为认证用户的替代方式。这种做法不属于 OAuth 标准或其安全注意事项的一部分,并且资源所有者可能并未 考虑到这一点。实现者在采用这种做法之前应该仔细查阅 资源服务器的文档。¶
本规范设计用于 HTTP [RFC9110]。在 HTTP 以外的任何协议上使用 OAuth 均超出本规范的范围。¶
自 OAuth 2.0 授权框架 [RFC6749] 于 2012 年 10 月发布以来,它已由原生应用的 OAuth 2.0 [RFC8252]、 OAuth 安全最佳当前实践 [RFC9700] 以及基于浏览器的应用的 OAuth 2.0 [I-D.ietf-oauth-browser-based-apps] 更新。 OAuth 2.0 授权框架:持有者令牌用法 [RFC6750] 也已由 [RFC9700] 更新。本 标准轨道规范整合了所有这些 文档中的信息,并移除了在 [RFC9700] 中被认定为不安全的功能。¶
OAuth 定义了四种角色:¶
能够授予对受保护资源访问权限的实体。 当资源所有者是个人时,将其称为 最终用户。有时缩写为“RO”。¶
托管受保护资源的服务器,能够使用访问令牌 接受并响应受保护资源请求。 资源服务器通常可通过 API 访问。 有时缩写为“RS”。¶
代表资源所有者并经其授权而发出受保护资源请求的 应用程序。“客户端”一词并不 暗示任何特定的实现特征(例如, 应用程序是在服务器、桌面设备还是其他 设备上执行)。¶
在成功认证资源所有者并获得授权后 向客户端颁发访问令牌的服务器。 有时缩写为“AS”。¶
本规范的大部分内容定义了客户端 与授权服务器之间的交互,以及客户端与资源服务器之间的交互。¶
授权服务器与资源服务器之间的交互 超出本规范的范围,不过已经定义了若干扩展,以 提供资源服务器与授权服务器之间实现互操作性的选项。 授权服务器可以与资源服务器位于同一服务器上,也可以是单独的实体。 单个授权服务器可以颁发由 多个资源服务器接受的访问令牌。¶
资源所有者与授权服务器之间的交互 (例如最终用户如何在授权服务器上认证自身) 同样超出本规范的范围,但也存在一些例外,例如 围绕提示最终用户同意的安全注意事项。¶
当资源所有者是最终用户时,用户将与 客户端交互。当客户端是基于 Web 的应用程序时,用户将 通过用户代理与客户端交互(如 第 3.5 节( [RFC9110])所述)。 当客户端是原生应用程序时,用户将通过操作系统 直接与客户端交互。有关更多详细信息,请参阅第 2.1 节。¶
+--------+ +---------------+
| |--(1)------ 授权请求 --------->| 资源 |
| | | 所有者 |
| |<-(2)------ 授权许可 ---------| |
| | +---------------+
| |
| | +---------------+
| |--(3)------ 授权许可 -------->| 授权 |
| 客户端 | | 服务器 |
| |<-(4)------ 访问令牌 ---------| |
| | +---------------+
| |
| | +---------------+
| |--(5)------ 访问令牌 -------->| 资源 |
| | | 服务器 |
| |<-(6)------ 受保护资源 -------| |
+--------+ +---------------+
图 1中所示的抽象 OAuth 2.1 流程描述了 四种角色之间的交互,并包括以下步骤:¶
客户端向资源所有者请求授权。 授权请求可以直接向资源所有者发出 (如图所示),也可以并且最好通过作为中介的授权 服务器间接发出。¶
客户端接收授权许可,它是一种 表示资源所有者授权的凭据, 使用本规范定义的某种授权许可类型 或扩展许可类型表示。 授权许可类型取决于客户端 请求授权所使用的方法以及授权服务器支持的类型。¶
客户端通过向授权服务器进行认证并 提交授权许可来请求访问令牌。¶
授权服务器认证客户端并验证 授权许可,如果有效,则颁发访问令牌。¶
客户端向资源服务器请求受保护资源, 并通过提交访问令牌进行认证。¶
资源服务器验证访问令牌,如果有效, 则处理该请求。¶
客户端从资源所有者获取授权许可 (步骤 (1) 和 (2) 所示)的首选方法是使用 授权服务器作为中介,如 第 4.1 节中的 图 3所示。¶
访问令牌是用于访问受保护资源的凭据。 访问令牌是表示颁发给 客户端的授权的字符串。¶
即使该字符串具有 某种结构,对于客户端而言也被视为不透明值。客户端不得期望能够解析访问 令牌的值。除了资源服务器所 预期的编码或格式之外,授权服务器无需对 访问令牌使用一致的编码或格式。¶
资源所有者授予客户端的访问权限由 授权服务器创建的访问令牌表示。访问令牌 的生命周期较短,以减小访问令牌泄露后的影响范围。访问 令牌的到期时间由授权服务器设置。¶
根据授权服务器的实现方式, 资源服务器可以使用令牌字符串检索授权信息, 也可以让令牌以可验证的方式自身包含授权信息 (即,由已签名的数据负载组成的令牌字符串)。令牌检索机制的一个示例 是令牌内省 [RFC7662],其中 RS 调用 AS 上的端点来验证客户端提交的令牌。 结构化令牌格式的一个示例是访问令牌的 JWT 配置文件 [RFC9068], 它是一种将访问令牌数据编码并签署为 JSON Web Token [RFC7519] 的方法。¶
为了让客户端使用访问令牌, 可能还需要本规范范围之外的额外认证凭据。 这通常称为发送方约束的 访问令牌,例如 DPoP [RFC9449] 和 绑定相互 TLS 证书的访问令牌 [RFC8705]。¶
访问令牌提供了一个抽象层,将不同的 授权构造(例如用户名和密码)替换为资源服务器能够理解的单个 令牌。这种抽象使得 可以颁发比用于获取访问令牌的授权许可 限制更多的访问令牌,同时也消除了资源服务器 理解大量认证方法的需要。¶
访问令牌可以根据资源 服务器的安全要求采用不同的格式、结构和 使用方法(例如密码学属性)。访问令牌属性以及 用于访问受保护资源的方法可以扩展到 本规范所述内容之外。¶
访问令牌(以及任何机密的访问令牌 属性)在传输和存储过程中必须保持机密,并且 只能在授权服务器、该访问令牌对其有效的资源服务器 以及该访问令牌所颁发给的客户端之间共享。¶
授权服务器必须确保未经授权的参与方无法 生成、修改或猜测出有效的访问令牌。¶
访问令牌旨在向客户端颁发比 授予访问权限的用户所拥有权限更少的 权限。这称为具有有限“作用域”的 访问令牌。授权服务器和资源服务器可以使用这种 作用域机制来限制特定客户端可以访问哪些类型的资源或具有何种访问级别。¶
例如,客户端可能只需要对用户 资源的“读取”访问权限,而不需要更新资源,因此客户端可以请求 授权服务器定义的只读作用域,并获取 无法用于更新资源的访问令牌。这需要 授权服务器、资源服务器和客户端之间进行协调。授权 服务器使客户端能够请求特定 作用域,并将这些作用域与颁发给客户端的访问令牌相关联。 然后,资源服务器负责在收到 有限作用域访问令牌时实施相应的作用域限制。¶
OAuth 不定义任何作用域值,而是由 授权服务器、OAuth 的扩展或配置文件来定义作用域。定义作用域的一个此类扩展 是 [OpenID.Connect],它定义了一组 可提供对用户个人资料信息细粒度访问的作用域。 建议避免定义与已知扩展中的作用域相冲突的自定义作用域。¶
为了请求有限作用域的访问令牌,客户端根据
所使用的许可类型,在授权端点或令牌端点使用
scope
请求参数。相应地,授权服务器使用 scope
响应参数告知客户端所颁发访问令牌的作用域。¶
scope 参数的值表示为空格分隔的 区分大小写的字符串列表。这些字符串由 授权服务器定义。如果该值包含多个由空格分隔的 字符串,它们的顺序无关紧要,并且每个字符串都会为请求的作用域 增加一个额外的访问范围。¶
scope = scope-token *( SP scope-token )
scope-token = 1*( %x21 / %x23-5B / %x5D-7E )
¶
授权服务器可以根据授权服务器策略或
资源所有者的指示,完全或部分忽略客户端请求的作用域。
如果所颁发访问令牌的作用域
与客户端请求的作用域不同,授权
服务器必须在令牌响应
(第 3.2.3 节)中包含
scope 响应参数,以告知
客户端实际授予的作用域。¶
如果客户端在请求授权时省略 scope 参数, 授权服务器必须使用预定义的默认值处理 请求,或者让请求失败并指明作用域无效。 授权服务器应该记录其作用域要求和默认值(如果已定义)。¶
持有者令牌是一种安全令牌,其属性是任何 持有该令牌的参与方(“持有者”)都能以 任何其他持有该令牌的参与方可以使用的方式使用该令牌。使用持有者令牌 不要求持有者证明其拥有密码学密钥材料 (持有证明)。¶
持有者令牌可以通过持有证明 规范得到增强,例如 DPoP [RFC9449] 和 mTLS [RFC8705],从而提供 持有证明特性。¶
为了防止访问令牌泄露, 客户端与资源服务器之间的通信交互 必须使用第 1.5 节所述的 机密性和完整性保护。¶
持有者令牌的具体结构或格式没有要求。 如果持有者令牌是对授权信息的引用,则攻击者必须无法实际 猜出此类引用,例如使用足够长的 密码学随机字符串。如果持有者令牌使用编码机制将 授权信息包含在令牌本身中,则访问令牌必须使用 足以防止令牌被修改的完整性保护。访问令牌的 一种编码和签名机制在访问令牌的 JSON Web Token 配置文件 [RFC9068] 中进行了说明。¶
发送方约束的访问令牌会将 访问令牌的使用绑定到特定发送方。该发送方必须 证明其知道某个秘密,作为接收方 (例如资源服务器)接受该访问令牌的前提条件。¶
授权服务器和资源服务器应该使用用于 对访问令牌施加发送方约束的机制,例如 OAuth 持有证明演示 (DPoP)[RFC9449] 或 OAuth 2.0 的相互 TLS [RFC8705]。 有关防止被盗和泄露的 访问令牌遭到滥用,请参阅 第 4.10.1 节([RFC9700])。¶
建议在客户端与 资源服务器之间使用端到端 TLS。如果 TLS 流量需要在中间方处终止, 请参阅 第 4.13 节([RFC9700])以获取进一步的安全建议。¶
实现必须使用一种机制来提供通信 认证、完整性和机密性,例如 传输层安全 [RFC9846], 以保护内容或标头字段中的明文凭据和令牌 在交换过程中免遭窃听,而窃听可能导致重放 (例如,参见第 2.4.1 节、第 7.5.1 节、第 3.2 节以及第 1.4.2 节)。¶
所有 OAuth 协议 URL(AS、RS 和客户端暴露的 URL)都必须使用
https 方案,
但环回接口重定向 URI 除外,
后者可以使用 http 方案。
使用 https 时,必须根据 第 4.3.4 节([RFC9110])
检查 TLS 证书。
在撰写本文时,
TLS 1.3 版 [RFC9846] 是最新
版本。¶
实现还可以支持满足其安全要求的其他 传输层安全机制。¶
TLS 版本和算法的确定 超出本规范的范围。 有关传输层安全的最新建议,请参阅 [BCP195], 有关证书验证和其他安全注意事项,请参阅相关 规范。¶
本规范广泛使用 HTTP 重定向,其中 客户端或授权服务器会将资源所有者的 用户代理引导到另一个目的地。尽管本 规范中的示例展示了 HTTP 302 状态码的使用,但除 HTTP 307 之外,任何其他可通过用户代理完成此重定向的 方法都是允许的,并被视为 实现细节。有关详细信息,请参阅第 7.5.4 节。¶
OAuth 2.1 提供了一个具有明确定义 安全属性的丰富授权框架。¶
本规范将一些必需组件保留为部分定义或完全 未定义(例如客户端注册、授权服务器能力、 端点发现)。其中一些行为在可选 扩展中进行了定义,实现可以选择使用这些扩展,例如:¶
本规范未定义
client_id、授权码、访问令牌、刷新令牌或
大多数其他协议参数的最大长度,因为这些值的长度取决于
颁发它们的一方所做的实现选择。在
实践中,实现会施加自己的限制,而超过
接收方实现限制的值将导致请求
失败。¶
实现不得假定其接收到的值适合 某个特定长度。颁发值的一方应该记录 其长度,并且应该考虑到将承载该值的组件的 限制。特别是,在重定向中返回的值, 例如授权码,会承载在 URI 查询字符串中,并且 HTTP 实现通常会限制请求行以及 单个标头字段的长度(第 3 节 ([RFC9112])和 第 5.4 节([RFC9110]))。 实现应该支持足够长的参数 值,以使请求保持在 第 3 节 ([RFC9112])建议的 8000 个八位字节的 请求行长度以内。资源 服务器尤其不应该对访问令牌的长度施加过小限制, 因为结构化格式的令牌(例如 [RFC9068] 中定义的令牌)通常会超过一 千字节。¶
OAuth 2.1 与 OAuth 2.0 兼容,同时应用了已知最佳当前实践中的扩展和限制。 具体而言,OAuth 2.0 核心中未规定的功能 (例如 PKCE)在 OAuth 2.1 中是必需的。此外, OAuth 2.0 中可用的某些功能,例如隐式许可或资源所有者凭据 许可类型,在 OAuth 2.1 中没有规定。此外,OAuth 2.0 中允许的某些行为 在 OAuth 2.1 中受到限制,例如 OAuth 2.1 要求 对重定向 URI 进行严格字符串匹配。¶
本文档中的关键词“MUST(必须)”、“MUST NOT(不得)”、“REQUIRED(必需)”、“SHALL(必须)”、“SHALL NOT(不得)”、“SHOULD(应该)”、“SHOULD NOT(不应该)”、“RECOMMENDED(建议)”、“NOT RECOMMENDED(不建议)”、 “MAY(可以)”和“OPTIONAL(可选)”,仅当它们像此处所示以 全大写形式出现时,才应按照 BCP 14 [RFC2119] [RFC8174] 中的说明进行解释。¶
本规范使用 [RFC5234] 的 扩充巴科斯-瑙尔形式(ABNF)表示法。此外,还从 “统一资源标识符(URI):通用语法” [RFC3986] 中引入了规则 URI-reference。¶
某些与安全相关的术语应按照 [RFC4949] 中定义的含义理解。这些术语包括但不限于: “攻击”、“认证”、“授权”、“证书”、 “机密性”、“凭据”、“加密”、“身份”、“签署”、 “签名”、“信任”、“验证”和“核验”。¶
术语“内容”应按照 第 6.4 节( [RFC9110])中的说明进行解释。¶
术语“用户代理”应按照 第 3.5 节( [RFC9110])中的说明进行解释。¶
除非另有说明,否则所有协议参数名称和值 都区分大小写。¶
在启动协议之前,客户端必须已在 授权服务器处建立一个标识符(第 2.2 节)。客户端标识符在 授权服务器处建立的方式超出本 规范的范围,但通常包括客户端开发者在授权服务器的网站上手动注册 客户端(创建账户并同意 服务条款之后),或者使用动态客户端注册 [RFC7591]。 扩展还可以定义其他以编程方式建立客户端注册的方法。¶
客户端注册不要求客户端与 授权服务器之间进行直接交互。如果 授权服务器支持,则注册可以依赖其他方式来 建立信任并获取所需的客户端属性 (例如重定向 URI、客户端类型)。例如,注册可以 使用自签发或第三方签发的断言来完成, 或由授权服务器通过受信任 通道执行客户端发现来完成。¶
客户端注册必须包括:¶
授权服务器要求的任何其他信息 (例如应用程序名称、网站、描述、徽标图像、 接受法律条款)。¶
动态客户端注册 [RFC7591] 定义了一个通用的数据模型, 即使使用手动客户端注册也可以使用该模型。¶
OAuth 2.1 根据客户端与授权服务器进行安全认证的能力 定义了两种客户端类型。¶
任何拥有凭据的客户端都必须采取预防措施,防止其凭据 泄露和被滥用。¶
客户端认证使授权服务器能够确保其在 OAuth 流程中
与某个特定客户端
(由其 client_id 标识)进行交互。授权服务器可能会根据其确信自己确实在与
合法客户端通信的程度,对诸如是否每次授权都提示用户同意,
还是仅第一次提示等事项做出
策略决定。¶
授权服务器是否以及如何验证客户端或 提供/运营该客户端的一方的身份,超出本规范的范围。 授权服务器在决定是否允许客户端访问更敏感的资源和操作 (例如客户端凭据许可类型),以及多久提示一次用户同意时, 应该考虑对客户端身份的可信程度。¶
授权服务器没有支持某种特定 客户端类型的要求。¶
单个 client_id 不应该被视为一种以上类型的
客户端。¶
本规范围绕以下客户端配置文件进行设计:¶
Web 应用程序是在 Web 服务器上运行的客户端。资源所有者通过其所使用设备上的用户代理中 渲染的 HTML 用户 界面访问客户端。客户端凭据以及颁发给客户端的任何访问 令牌均存储在 Web 服务器上,并且 不会暴露给资源所有者,也无法由资源所有者访问。¶
基于浏览器的应用程序是一种客户端,其中 客户端代码从 Web 服务器下载,并在 资源所有者所使用设备上的用户代理(例如 Web 浏览器)中执行。 资源所有者很容易访问(并且 通常可以看到)协议数据和凭据。如果此类应用程序希望使用 客户端凭据,建议采用 前端后端模式。由于此类应用程序 驻留在用户代理内,因此它们在请求授权时可以无缝使用 用户代理的能力。¶
原生应用程序是安装并执行在 资源所有者所使用设备上的客户端。协议数据和 凭据可由资源所有者访问。假定 应用程序中包含的任何客户端认证凭据 都可以被提取。动态 颁发的访问令牌和刷新令牌可以 获得可接受级别的保护。在某些平台上,这些凭据 可免受同一 设备上其他应用程序的访问。如果此类应用程序希望使用 客户端凭据,建议采用 前端后端模式,或者在运行时 使用动态客户端注册 [RFC7591] 颁发凭据。¶
在授权服务器的上下文中,每个客户端都由 客户端标识符来标识——它是表示客户端所提供注册 信息的唯一字符串。虽然授权服务器通常 自行颁发客户端标识符,但它也可以为客户端标识符 由授权服务器之外的一方创建的客户端提供服务。客户端标识符不是 秘密;它会暴露给资源所有者,并且不得单独用于 客户端认证。客户端标识符在 授权服务器的上下文中是唯一的。¶
客户端标识符是一个不透明字符串,其长度由本 规范保持未定义,如第 1.7.1 节所述。¶
如果授权服务器支持客户端标识符由 授权服务器之外的其他方颁发的客户端,则授权服务器应该 采取预防措施,避免客户端如第 7.4 节所述 冒充资源所有者。¶
客户端重定向端点(也称为“重定向端点”) 是授权服务器在完成与资源所有者的交互后, 将用户代理重定向回客户端时所使用的客户端 URI。¶
授权服务器会将用户代理重定向到 在客户端注册过程中预先与 授权服务器建立的客户端重定向端点之一。¶
重定向 URI 必须是 第 4.3 节( [RFC3986])定义的绝对 URI。重定向 URI 可以包含 查询字符串组成部分(附录 C.1),并且在添加 其他查询参数时必须保留该组成部分。重定向 URI 不得包含 片段组成部分。¶
授权服务器必须要求客户端注册其完整的 重定向 URI(包括路径组成部分)。授权服务器 必须拒绝指定了与已注册 URI 不 完全匹配的重定向 URI 的授权请求,但 环回重定向除外;对于环回重定向,除 端口 URI 组成部分之外,其余部分都要求完全匹配,详见第 4.1.1 节。¶
授权服务器可以允许客户端注册多个 重定向 URI。¶
注册可以在带外进行,例如在授权服务器处手动配置 客户端信息, 也可以在运行时进行,例如推送授权请求 [RFC9126] 中的初始 POST。¶
对于基于私有使用 URI 方案的重定向 URI,授权
服务器应该实施第 8.4.3
节中的要求,即客户端使用
基于反向域名的方案。至少,任何
不包含句点字符(.)的私有使用 URI 方案
都应该被拒绝。¶
除了抗冲突属性之外,
当两个应用声称使用同一私有使用 URI 方案
(其中一个应用具有恶意行为)发生争议时,这还有助于证明所有权。
例如,如果两个应用都声称使用 com.example.app,
example.com 的所有者可以请求应用商店运营方
移除仿冒应用。如果使用的是
通用 URI 方案,则此类请求更难得到证明。¶
客户端不得暴露可将用户浏览器转发到 从查询参数获取的任意 URI 的 URL(“开放重定向器”),如 第 7.13 节所述。 开放重定向器可能导致 授权码和访问令牌被外泄。¶
如果需要,客户端可以使用 state 请求参数
实现每请求
自定义,而不是在每个请求中改变重定向 URI。¶
如果为客户端注册了多个重定向 URI,则
客户端必须在授权请求中使用
redirect_uri 请求参数包含一个重定向 URI(第 4.1.1 节)。
如果仅为客户端注册了一个重定向 URI,
则 redirect_uri 请求参数是可选的。¶
客户端必须防止跨站请求伪造(CSRF)攻击。在此
上下文中,CSRF 指的是发送到重定向端点、但并非
源自授权服务器,而是源自恶意第三方的请求
(详见 第
4.4.1.8 节([RFC6819]))。已经
确保授权服务器支持 code_challenge 参数的客户端可以
依赖该机制提供的 CSRF 保护。在 OpenID Connect 流程中,
验证 nonce 参数可提供 CSRF 保护。否则,
必须使用通过 state 参数携带并安全
绑定到用户代理的一次性
CSRF 令牌来提供 CSRF 保护(参见
第 7.10 节)。¶
当 OAuth 客户端只能与一个授权 服务器交互时,不需要混淆防御。但是,在 OAuth 客户端与 两个或更多授权服务器交互的场景中,客户端必须防止混淆攻击。 为了防止混淆攻击,客户端只能处理与其发送相应请求的 发行者相对应的重定向响应,并且必须来自发起该 授权请求的同一个用户代理。¶
发送到客户端端点的重定向请求通常会产生 一个由用户代理处理的 HTML 文档响应。如果 HTML 响应直接作为重定向请求的结果提供, HTML 文档中包含的任何脚本都将在可完全 访问重定向 URI 及其中所含工件(例如授权码)的情况下执行。 此外,包含授权码的请求 URL 可能会在 HTTP Referer 标头中发送给页面中加载的任何嵌入图像、样式表 和其他元素。¶
客户端不应该在重定向 URI 端点响应中包含任何第三方脚本(例如第三方 分析、社交插件、广告网络)。相反,它应该从 URI 中提取工件,并再次将用户代理重定向到另一个端点, 且不暴露这些工件(无论是在 URI 中还是其他位置)。如果包含第三方 脚本,客户端必须确保其自己的脚本 (用于从 URI 中提取并移除凭据) 首先执行。¶
只有在底层凭据的 颁发/注册和分发过程能够确保其机密性的情况下, 授权服务器才必须依赖客户端认证。¶
对于机密客户端,授权服务器可以接受任何 满足其安全要求的客户端认证形式 (例如客户端密钥、公钥/私钥对)。¶
建议对客户端认证使用非对称(基于公钥的)方法,
例如 mTLS [RFC8705],或根据 [RFC7521]、[RFC7523]
及其更新 [I-D.ietf-oauth-rfc7523bis]
使用已签名的 JWT
(“私钥 JWT”)
(在 [OpenID.Connect] 中定义为
客户端认证方法 private_key_jwt)。
使用此类客户端认证方法时,授权
服务器无需存储敏感的对称密钥,这使这些
方法能够更稳健地抵御多种攻击,并使客户端
能够管理自己的密钥和密钥轮换。¶
使用基于 JWT 的客户端认证时,客户端和授权服务器
必须遵循 [I-D.ietf-oauth-rfc7523bis] 中有关 aud 值的更新指南。¶
当无法进行客户端认证时,授权服务器 应该使用其他方式验证客户端身份——例如, 要求注册客户端重定向 URI 或请求资源所有者确认身份。在请求资源所有者授权时, 有效的重定向 URI 本身不足以验证客户端身份, 但可以用来防止在获得资源所有者授权后 将凭据交付给仿冒客户端。¶
客户端在每个请求中不得使用一种以上的认证方法, 以避免出现哪个认证机制 对该请求具有权威性的冲突。¶
授权服务器必须考虑 与未经认证的客户端交互所带来的安全影响,并采取措施限制 向此类客户端颁发的令牌可能暴露的风险 (例如限制刷新令牌的生命周期)。¶
授权服务器与某个 客户端身份相关联的权限,必须取决于对客户端识别和 客户端凭据生命周期管理整体过程的评估。 有关更多详细信息,请参阅第 7.2 节。¶
为了支持拥有客户端密钥的机密客户端, 授权服务器必须支持客户端使用以下 参数在请求正文内容中包含客户端凭据:¶
这些参数只能在请求内容中传输, 不得包含在请求 URI 中。¶
这也称为 client_secret_post,如
第
2 节([RFC7591])中所定义。¶
例如,使用内容参数刷新访问令牌(第 4.3 节)的请求 如下(仅为显示目的添加额外换行):¶
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¶
授权服务器可以支持 HTTP Basic 认证方案,以认证已向其颁发 客户端密钥的客户端。¶
当使用 第
11 节([RFC9110])
定义的 HTTP Basic 认证方案
向授权服务器进行认证时,客户端标识符按照
附录 B使用
application/x-www-form-urlencoded 编码算法进行编码,
并将编码后的值用作用户名;客户端
密钥使用相同算法编码,并用作
密码。¶
这也称为 client_secret_basic,如
第
2 节([RFC7591])中所定义。¶
例如(仅为显示目的添加额外换行):¶
Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3¶
注意:这种先对客户端标识符和密钥进行表单编码, 然后将编码后的值用作 HTTP Basic 认证用户名 和密码的方法,过去曾导致许多互操作性问题。一些 实现遗漏了编码步骤,或决定仅编码 某些字符,或在验证 凭据时忽略了编码要求,导致客户端不得不针对 不同授权服务器以特殊方式提交 凭据。将凭据包含在请求正文内容中可以避免编码问题,并实现 更具互操作性的实现。¶
由于客户端密钥认证方法涉及密码, 授权服务器必须保护任何使用该方法的端点免受 暴力破解攻击。¶
授权服务器可以支持任何符合其安全要求的适当认证 方案。使用其他 认证方法时,授权服务器必须定义 客户端标识符(注册记录)与 认证方案之间的映射。¶
一些其他认证方法,例如 mTLS [RFC8705] 和私钥 JWT([RFC7523]、 [I-D.ietf-oauth-rfc7523bis]) 定义在 “OAuth 令牌端点认证方法”注册表中, 并且可以用作通用客户端认证方法,而不仅限于 保护令牌端点这一特定用途。¶
授权过程使用两个授权服务器端点 (HTTP 资源):¶
以及一个客户端端点:¶
重定向端点——授权服务器用于通过 资源所有者的用户代理向客户端返回包含授权凭据的 响应。¶
并非每种授权许可类型都会使用这两个端点。 扩展许可类型可以按需要定义其他端点。¶
客户端使用令牌端点,通过 第 4 节和 第 4.3 节中所述之类的许可 获取访问令牌。¶
客户端获取令牌 端点 URL 的方式超出本规范的范围,但该 URL 通常在服务文档中提供,并在 客户端开发期间进行配置,或者由授权服务器的元数据 文档 [RFC8414] 提供,并在 运行时以编程方式获取。¶
令牌端点 URL 不得包含片段组成部分, 并且可以包含查询字符串组成部分(附录 C.1)。¶
客户端向令牌端点发出请求时必须使用 HTTP POST 方法。¶
授权服务器必须忽略发送到 令牌端点的无法识别的请求参数。¶
未带值发送的参数必须被视为 已从请求中省略。本规范定义的请求和响应参数 不得出现多次。 这一要求也适用于扩展定义的参数, 除非扩展明确为某个特定 参数另作规定。¶
希望支持基于浏览器的应用程序的授权服务器 (例如,仅在客户端 JavaScript 中运行且 无法访问支持性后端服务器的应用程序)需要确保令牌端点 支持必要的 CORS [WHATWG.CORS] 标头,以允许应用程序看到 响应。 如果授权服务器向应用程序提供其他端点,例如 元数据 URL、动态客户端注册、撤销、内省、发现或 用户信息端点,则基于浏览器的 应用程序也可能访问这些端点,并且这些端点也需要定义允许访问的 CORS 标头。 有关更多详细信息,请参阅 [I-D.ietf-oauth-browser-based-apps]。¶
客户端通过使用 附录 C.2规定的表单编码序列化 格式,并在 HTTP 请求内容中采用 UTF-8 字符编码发送以下参数,来向令牌端点发出请求:¶
必需。客户端在特定令牌请求中使用的
许可类型标识符。
本规范定义了值 authorization_code、
refresh_token 和 client_credentials。
许可类型决定令牌请求需要或支持的
其他参数。这些许可类型的
详细信息在下文定义。¶
可选。当使用依赖该参数的
客户端认证形式,或者 grant_type 要求
识别公共客户端时,需要客户端标识符。¶
机密客户端必须按照第 3.2.1 节所述向授权 服务器进行认证。¶
例如,客户端发出以下 HTTPS 请求 (仅为显示目的添加额外换行):¶
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 &code_verifier=3641a2d12d66101249cdf7a79c000c1f8c05d2aafcf14bf146497bed¶
授权服务器必须:¶
还适用其他特定于许可类型的处理规则,这些规则在相应的 许可类型中规定。¶
如果访问令牌请求有效且已获授权, 授权服务器将颁发访问令牌以及可选的刷新 令牌。¶
如果客户端认证失败或无效,授权 服务器将返回第 3.2.4 节中所述的错误响应。¶
授权服务器按照附录
C.3创建 HTTP 响应,
使用 [RFC8259]定义的
application/json 媒体类型,
并包含以下参数及 HTTP 200(OK)状态码,
以颁发访问令牌以及可选的刷新令牌:¶
必需。授权 服务器颁发的访问令牌。¶
建议。一个表示访问令牌生命周期(以秒为单位)的
JSON 数字。例如,值 3600 表示访问令牌将在
响应生成后的一小时过期。
如果省略,授权服务器应该通过其他方式提供该
生命周期,或者记录默认值。请注意,
授权服务器可能会提前使访问
令牌过期,因此客户端不得期望访问令牌在所提供的
生命周期内始终有效。¶
可选。刷新令牌,可用于 根据相应令牌请求中传递的许可 获取新的访问令牌。¶
授权服务器应该根据风险评估 以及其自身策略,决定是否向某个客户端颁发刷新令牌。如果 授权服务器决定不颁发刷新令牌,客户端 可以通过重新开始 OAuth 流程来获取新的访问令牌,例如 发起新的授权码请求。在这种情况下,授权 服务器可以利用 Cookie 和持久许可来优化用户 体验。¶
如果颁发刷新令牌,这些刷新令牌必须绑定到 资源所有者同意的作用域和资源服务器。 这是为了防止合法客户端提升权限,并 降低刷新令牌泄露的影响。¶
这些参数按照附录 C.3中的说明序列化为 JavaScript Object Notation (JSON) 结构。¶
授权服务器在任何
包含令牌、凭据或其他敏感
信息的响应中,都必须包含 HTTP
Cache-Control
响应标头字段(参见 第
5.2 节([RFC9111])),其值为
no-store。¶
例如:¶
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
{
"access_token": "2YotnFZFEjr1zCsicMWpAA",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter": "example_value"
}
¶
客户端必须忽略响应中无法识别的值名称。 从授权服务器接收到的令牌及其他值的长度 保持未定义,如第 1.7.1 节所述。¶
授权服务器使用 HTTP 400(错误请求) 状态码进行响应(除非另有规定),并在响应中包含以下 参数:¶
必需。以下错误代码之一的单个 ASCII [USASCII] 值:¶
请求缺少必需参数、
包含不支持的参数值(许可类型除外)、
重复某个参数、包含多个凭据、
使用一种以上机制来认证
客户端、虽然授权请求中未发送
code_challenge 却包含 code_verifier,
或者以其他方式格式错误。¶
客户端认证失败(例如未知
客户端、未包含客户端认证或不支持的
认证方法)。授权服务器可以
返回 HTTP 401(未授权)状态码,以指明
支持哪些 HTTP 认证方案。如果
客户端尝试通过 Authorization
请求标头字段进行认证,则授权服务器必须
使用 HTTP 401(未授权)状态码进行响应,并
包含与客户端所使用认证方案相匹配的
WWW-Authenticate 响应标头字段。¶
所提供的授权许可(例如 授权码、资源所有者凭据)或刷新令牌 无效、已过期、已撤销、与授权请求中使用的 重定向 URI 不匹配,或颁发给了 另一个客户端。¶
已认证的客户端无权 使用此授权许可类型。¶
授权服务器不支持该 授权许可类型。¶
请求的作用域无效、未知、 格式错误,或 超出了资源所有者授予的作用域。¶
error 参数的值不得
包含集合 %x20-21 / %x23-5B / %x5D-7E 之外的字符。¶
可选。人类可读的 ASCII [USASCII] 文本,用于提供
附加信息,以帮助客户端开发者
理解所发生的错误。
error_description 参数的值不得包含
集合 %x20-21 / %x23-5B / %x5D-7E 之外的字符。¶
可选。一个标识人类可读网页的 URI,
该网页包含有关错误的信息,用于向客户端
开发者提供有关错误的附加信息。
error_uri 参数的值必须符合
URI-reference 语法,因此不得包含
集合 %x21 / %x23-5B / %x5D-7E 之外的字符。¶
这些参数使用附录
C.3中定义的
application/json 媒体类型包含在 HTTP 响应内容中。¶
例如:¶
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store
{
"error": "invalid_request"
}
¶
客户端通过向资源服务器提交访问 令牌来访问受保护资源。资源服务器必须验证 访问令牌,并确保它尚未过期且其作用域 覆盖所请求的资源。资源 服务器用于验证访问令牌的方法 超出本规范的范围,但通常涉及 资源服务器与 授权服务器之间的交互或协调。例如,当资源服务器与 授权服务器位于同一处或属于同一系统时, 它们可以共享数据库或其他存储;当两个组件 独立运行时,它们可以使用令牌内省 [RFC7662] 或诸如 JWT [RFC9068] 这样的结构化访问令牌格式。¶
本节定义了在向资源服务器发出的资源 请求中发送持有者令牌的两种方法。客户端必须使用下面定义的两种方法之一, 并且每个请求中不得使用一种以上的方法传输令牌。¶
特别是,客户端不得在 URI 查询 参数中发送访问令牌, 并且资源服务器必须忽略 URI 查询参数中的访问令牌。¶
在 HTTP 请求内容中发送访问令牌时,
客户端使用
access_token 参数将访问令牌添加到请求内容中。除非
满足以下所有条件,否则客户端不得使用此方法:¶
HTTP 请求包含设置为
application/x-www-form-urlencoded 的 Content-Type
标头
字段。¶
内容遵循 URL 现行标准 [WHATWG.URL] 定义的
application/x-www-form-urlencoded 内容类型的编码要求。¶
HTTP 请求内容为单部分。¶
HTTP 请求方法必须是其内容具有
已定义语义的方法。特别是,这意味着不得使用 GET
方法。¶
内容可以包含其他特定于请求的参数,在
这种情况下,必须使用 & 字符(ASCII
代码 38)将 access_token 参数与特定于请求的参数正确分隔。¶
例如,客户端使用 传输层安全发出以下 HTTP 请求:¶
POST /resource HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded access_token=mF_9.B5f-4.1JqM¶
除非应用程序上下文中的参与客户端无法
访问 Authorization 请求标头字段,否则不应该
使用 application/x-www-form-urlencoded 方法。资源
服务器可以支持此方法。¶
收到访问令牌后,资源服务器必须检查 访问令牌尚未过期、已获准访问所请求的 资源、颁发时具有适当的作用域,并满足资源服务器访问受保护资源的其他策略 要求。¶
访问令牌通常分为两类:引用令牌或 自编码令牌。 引用令牌可以通过查询授权服务器或 在令牌数据库中查找令牌来验证,而自编码令牌 将授权信息包含在加密和/或签名的字符串中, 资源服务器可以从中提取该信息。¶
令牌内省 [RFC7662] 定义了查询授权服务器以检查访问令牌有效性的标准化方法。¶
如果资源访问请求失败,资源服务器应该告知 客户端该错误。错误响应的详细信息由特定令牌 类型决定,例如第 5.3.2 节中对持有者令牌的 说明。¶
如果受保护资源请求不包含认证
凭据,或者不包含能够访问
受保护资源的访问令牌,则资源服务器必须包含 HTTP
WWW-Authenticate 响应标头字段;它也可以在
响应其他条件时包含该字段。WWW-Authenticate 标头
字段使用 HTTP/1.1 [RFC7235] 定义的框架。¶
此令牌类型的所有质询都必须使用 auth-scheme
值 Bearer。此方案后面必须跟随一个或多个
auth-param 值。本
规范为此令牌类型使用或定义的 auth-param 属性如下。也可以使用其他 auth-param
属性。¶
可以包含 realm 属性,以
按照 HTTP/1.1 [RFC7235]
中所述的方式指明
保护范围。
realm 属性不得出现多次。¶
scope 属性在第 1.4.1 节中定义。
scope 属性是以空格分隔的区分大小写的作用域
值列表,用于指明访问所请求资源时
访问令牌所需的作用域。scope 值由实现
定义;不存在集中式注册表;允许的值
由授权服务器定义。scope 值的顺序
无关紧要。在某些情况下,scope 值会在请求
具有足够访问作用域、可以使用受保护资源的新访问令牌时使用。
scope 属性的使用是
可选的。scope 属性不得出现多次。
scope 值旨在供程序使用,不应
显示给最终用户。¶
下面给出两个示例作用域值;它们分别取自 OpenID Connect [OpenID.Messages] 和开放 认证技术 委员会(OATC)在线多媒体授权协议 [OMAP] 的 OAuth 2.0 用例:¶
scope="openid profile email" scope="urn:example:channel=HBO&urn:example:rating=G,PG-13"¶
如果受保护资源请求包含访问
令牌但认证失败,资源服务器应该包含 error
属性,以向客户端提供访问
请求被拒绝的原因。参数值在
第
5.3.2 节中说明。¶
资源服务器可以包含
error_description 属性,为开发者提供人类可读的
说明,该说明并非用于向最终用户显示。¶
资源服务器可以包含
error_uri 属性,其值是一个绝对 URI,
用于标识解释该错误的人类可读网页。¶
error、error_description 和
error_uri 属性均不得
出现多次。¶
scope 属性的值(在附录 A.4中规定)
不得包含用于表示作用域值的集合 %x21 / %x23-5B
/ %x5D-7E 以及用于
作用域值之间分隔符的 %x20 之外的字符。error 和
error_description
属性的值(分别在附录
A.7和附录
A.8中规定)不得
包含集合 %x20-21 / %x23-5B / %x5D-7E 之外的字符。
error_uri 属性的值(在附录
A.9中规定)
必须符合 URI-reference 语法,因此不得
包含集合 %x21 / %x23-5B / %x5D-7E 之外的字符。¶
当请求失败时,资源服务器使用适当的 HTTP 状态码(通常为 400、401、403 或 405)进行响应,并 在响应中包含以下错误代码之一:¶
请求缺少必需参数、包含 不支持的参数或参数值、重复相同的 参数、使用一种以上的方法包含访问 令牌,或者存在其他格式错误。资源服务器应该 使用 HTTP 400(错误请求)状态码进行响应。¶
所提供的访问令牌已过期、已撤销、 格式错误或 因其他原因无效。资源服务器应该使用 HTTP 401(未授权)状态码进行响应。客户端可以 请求新的访问令牌并重试受保护资源 请求。¶
请求所需的权限(作用域)高于
授予客户端并由访问令牌表示的
作用域所提供的权限。
资源服务器应该使用 HTTP
403(禁止)状态码进行响应,并且可以包含
scope 属性,其中包含访问受保护
资源所需的作用域。¶
扩展可以定义其他错误代码,或者指定返回上述错误代码的其他 情形。¶
如果请求缺少任何认证信息(例如, 客户端 不知道需要认证,或尝试使用 不受支持的认证方法),资源服务器不应该 包含错误代码或其他错误信息。¶
例如:¶
HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer realm="example"¶
而对于使用已过期访问令牌尝试 认证的受保护资源请求,则响应如下:¶
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example",
error="invalid_token",
error_description="访问令牌已过期"
¶
访问令牌类型可以通过两种方式之一进行定义:在 访问令牌类型注册表中注册(遵循 第 11.1 节 ([RFC6749])中的程序),或者使用唯一的绝对 URI 作为其名称。¶
[RFC6750] 在 第 11.4 节([RFC6749]) 中建立了一个通用注册表,用于在 OAuth 令牌认证方案之间共享错误值。¶
主要为 OAuth 令牌 认证设计的新认证方案应该定义一种向客户端提供错误 状态码的机制,其中允许的错误值 注册在本规范建立的错误注册表中。¶
此类方案可以将有效错误代码集限制为
已注册值的子集。如果错误代码使用命名
参数返回,则参数名称应该是 error。¶
其他能够用于 OAuth 令牌认证, 但并非主要为此目的设计的方案,也可以以相同方式将其错误 值绑定到该注册表。¶
新认证方案还可以选择规定使用
error_description 和 error_uri 参数,以与本
规范中的用法类似的方式返回错误
信息。¶
类型名称必须符合
type-name ABNF。如果类型定义包含新的 HTTP
认证方案,则类型名称应该与 HTTP
认证方案名称(如 [RFC2617] 所定义)相同。令牌类型
example 保留用于示例。¶
type-name = 1*name-char name-char = "-" / "." / "_" / DIGIT / ALPHA¶
使用 URI 名称的类型应该仅限于 不具有普遍适用性的供应商特定实现,并且特定于 使用它们的资源服务器的实现细节。¶
所有其他类型都必须注册。¶
用于授权 端点或令牌端点的新请求或响应参数,按照 第 11.2 节 ([RFC6749])中的程序,在 OAuth 参数注册表中定义和注册。¶
参数名称必须符合 param-name ABNF,并且参数 值语法必须定义明确(例如,使用 ABNF,或者引用 现有参数的语法)。¶
param-name = 1*name-char name-char = "-" / "." / "_" / DIGIT / ALPHA¶
不具有普遍适用性且特定于 使用它们的授权服务器实现 细节的未注册供应商特定参数扩展,应该 使用不太可能与其他已注册值冲突的供应商特定前缀 (例如,以 'companyname_' 开头)。¶
用于授权端点的新响应类型 按照 第 11.3 节 ([RFC6749])中的程序,在授权端点响应类型 注册表中定义和注册。响应类型 名称必须符合 response-type ABNF。¶
response-type = response-name *( SP response-name ) response-name = 1*response-char response-char = "_" / DIGIT / ALPHA¶
如果响应类型包含一个或多个空格字符(%x20),则 将其作为以空格分隔的值列表进行比较,其中 值的顺序无关紧要。只能注册一种值的顺序, 它涵盖同一值集合的所有其他排列。¶
例如,扩展可以定义并注册
code other_token
响应类型。注册后,相同组合不能以
other_token code 的形式注册,但这两种值都可以用于
表示同一响应类型。¶
如果协议扩展(即访问令牌类型、 扩展参数或扩展许可类型)需要其他 错误代码与授权码许可错误 响应(第 4.1.2.1 节)、令牌错误响应(第 3.2.4 节)或 资源访问错误响应(第 5.3 节)一起使用,则可以 定义此类错误代码。¶
如果扩展错误代码所结合使用的扩展是 已注册访问令牌类型、已注册端点参数或 扩展许可类型,则扩展错误代码必须注册(遵循 第 11.4 节 ([RFC6749])中的程序)。与未注册扩展一起使用的错误代码 可以注册。¶
错误代码必须符合 error ABNF,并且在可能的情况下应该使用
标识名称作为前缀。例如,用于标识
扩展参数 example 被设置为无效值的错误,应该
命名为 example_invalid。¶
error = 1*error-char error-char = %x20-21 / %x23-5B / %x5D-7E¶
作为一个灵活且可扩展的框架,OAuth 的安全 注意事项取决于许多因素。以下各节 为实现者提供安全指南,重点针对第 2.1 节中描述的三种 客户端配置文件:Web 应用程序、 基于浏览器的应用程序和原生应用程序。¶
全面的 OAuth 安全模型和分析,以及 协议设计的背景,由 [RFC6819] 和 [RFC9700] 提供。¶
以下列表列出了针对使用某种形式令牌的协议的若干常见威胁。 此威胁列表基于 NIST 特别出版物 800-63 [NIST800-63]。¶
攻击者可能生成伪造的 访问令牌,或修改现有令牌的内容(例如认证或 属性声明),从而导致资源 服务器向客户端授予不适当的访问权限。例如, 攻击者可能修改令牌以延长有效期; 恶意客户端可能修改断言,以访问 其本不应能够查看的信息。¶
通过使用数字签名保护访问令牌的内容,并遵循 签名密钥管理的最佳实践(例如定期轮换密钥),可以缓解大量威胁。¶
或者,持有者令牌可以包含对 授权信息的引用,而不是直接编码该信息。 使用引用可能需要资源服务器与授权服务器之间进行一次额外交互, 以将该引用解析为 授权信息。此类交互的机制 未由本规范定义,但令牌内省 [RFC7662] 定义了其中一种机制。¶
本文档未规定访问令牌的编码或内容; 因此,有关保证访问令牌完整性保护手段的详细建议 超出本 规范的范围。访问令牌的一种编码和 签名机制在 访问令牌的 JSON Web Token 配置文件 [RFC9068] 中进行了说明。¶
为了应对访问令牌重定向,授权 服务器在令牌中包含预期接收方(即 受众)的身份非常重要,通常是单个资源服务器(或资源 服务器列表)。还建议将令牌的使用限制在 特定作用域内。¶
第 1.5 节提供了有关 防止访问令牌泄露,以及为 客户端、资源服务器和授权服务器之间的通信 提供机密性和完整性的信息。¶
客户端实现必须确保 持有者令牌不会泄露给非预期方,因为这些方将 能够使用令牌获取对受保护资源的访问权限。这 是使用持有者令牌时最主要的安全注意事项,并且 是后续所有更具体建议的基础。¶
客户端在向受保护资源发出请求时必须验证 TLS 证书链。 未能这样做可能使 DNS 劫持攻击能够窃取 令牌并获得非预期的访问权限。¶
客户端在使用持有者令牌发出请求时必须始终使用 TLS (https)或等效的传输安全机制。 未能这样做会使令牌暴露于多种 攻击,从而可能使攻击者获得非预期的访问权限。¶
授权服务器应该颁发 短生命周期的持有者令牌,尤其是在 向运行于 Web 浏览器或其他 可能发生信息泄露的环境中的客户端颁发令牌时。使用 短生命周期的持有者令牌可以减小它们 泄露所带来的影响。¶
授权服务器应该颁发 包含受众限制的持有者令牌,将其使用范围限定为 预期的资源服务器或资源服务器集合。¶
不得在 页面 URL 中传递持有者令牌(例如作为查询字符串参数)。 相反,持有者令牌应该在采取了机密性措施的 HTTP 消息标头或 消息正文中传递。 浏览器、Web 服务器及其他软件可能无法充分 保护浏览器历史记录、Web 服务器日志及其他 数据结构中的 URL。如果在页面 URL 中传递持有者令牌, 攻击者可能能够从历史数据、日志 或其他未受保护的位置窃取它们。¶
与访问令牌关联的权限应该限制为 特定应用程序或用例所需的最低权限。 这可防止客户端超出资源所有者授权的 权限。它还可防止用户超出相应安全策略 所授权的权限。权限 限制还有助于减小访问令牌泄露的影响。¶
特别是,访问令牌应该限制到某些
资源服务器(受众限制),最好限制到单个资源
服务器。为实现这一点,授权服务器将
访问令牌与某些资源服务器关联,并且每个资源
服务器都有义务针对每个请求验证随该请求发送的访问
令牌是否旨在用于该特定
资源服务器。如果不是,资源服务器必须拒绝处理
相应请求。客户端和授权服务器可以分别
使用本文档和 [RFC8707] 中规定的
scope 或 resource 参数,
以
确定它们希望访问的资源服务器。¶
此外,访问令牌应该限制到资源服务器上的某些
资源
和操作,或某些资源上的操作。为实现这一点,
授权服务器将访问令牌与相应资源和操作
相关联,并且每个资源服务器都有义务
针对每个请求验证随该请求发送的访问令牌是否旨在用于
该特定资源上的特定操作。如果不是,资源服务器必须拒绝
处理相应请求。客户端和授权服务器可以
使用参数 scope 以及
[RFC9396] 中规定的
authorization_details 来
确定这些资源和/或操作。¶
根据客户端注册和凭据 生命周期管理的整体过程,这可能会影响授权 服务器对特定客户端的可信程度。¶
例如,对动态注册客户端的认证并不能 证明客户端的身份,它仅确保向 授权服务器重复发出的请求来自同一个客户端实例。此类 客户端可以在允许请求哪些作用域方面受到限制, 或具有其他限制,例如更短的令牌生命周期。¶
相比之下,如果存在一个已注册应用程序,其开发者身份 已经过验证、签署了合同并获得仅用于安全后端服务的客户端密钥, 则授权 服务器可能允许此客户端请求更敏感的作用域, 或向其颁发生命周期更长的令牌。¶
如果机密客户端的凭据被窃取, 恶意客户端便可以冒充该客户端并获得对 受保护资源的访问权限。¶
授权服务器应该强制进行明确的资源所有者 认证,并向资源所有者提供有关 客户端以及所请求授权作用域和生命周期的信息。应由 资源所有者结合当前客户端的上下文审查这些信息,并 授权或拒绝请求。¶
授权服务器不应该在未经主动资源所有者交互的情况下自动处理重复的授权 请求, 除非认证了客户端,或者依赖其他措施 确保重复请求来自原始客户端,而 不是冒充者。¶
如上所述,授权 服务器不应该在没有用户同意或交互的情况下自动处理授权请求, 除非能够确认 客户端的身份。这包括用户 先前已经批准针对给定客户端 ID 的授权请求的情况—— 除非可以证明客户端的身份,否则该请求应该 按照此前没有批准过任何请求来处理。¶
授权服务器可以接受诸如声明的 https 方案重定向之类的措施作为
身份证明。
某些操作系统可能
提供其他平台特定的身份功能,在适当情况下也可以
接受这些功能。¶
客户端应该请求具有所需最小作用域的访问令牌。 授权服务器在决定如何满足所请求的作用域时应该考虑客户端身份, 并且可以 颁发作用域少于所请求作用域的访问令牌。¶
与访问令牌关联的权限应该限制为 特定应用程序或用例所需的最低权限。这 可防止客户端超出资源所有者授权的 权限。它还可防止用户超出相应安全策略 授权的权限。权限限制 还有助于减小访问令牌泄露的影响。¶
特别是,访问令牌应该限制到某些
资源服务器(受众限制),最好限制到单个资源
服务器。为实现这一点,授权服务器将
访问令牌与某些资源服务器相关联,并且每个资源
服务器都有义务针对每个请求验证随该请求发送的访问
令牌是否旨在用于该特定
资源服务器。如果不是,资源服务器必须拒绝处理
相应请求。客户端和授权服务器可以分别使用
[RFC8707] 中规定的
参数 scope 或 resource,以
确定它们希望访问的资源服务器。¶
资源服务器可能根据为其颁发访问令牌的
资源所有者身份,或者根据客户端凭据许可中的客户端身份来做出访问控制决定。
如果两种方式都可能适用,
根据实现的具体细节,客户端身份可能会被
误认为资源所有者身份。例如,如果客户端能够
在向授权服务器注册期间选择自己的 client_id,
恶意客户端可能将其设置为标识最终用户的值(例如,如果使用 OpenID Connect,则设置为 sub
值)。如果资源服务器无法正确
区分颁发给客户端的访问令牌与颁发给
最终用户的访问令牌,则客户端随后可能能够访问最终用户的资源。¶
如果授权服务器为客户端 ID 和用户
标识符使用公共命名空间,从而导致资源服务器无法区分由资源所有者授权的访问
令牌与由客户端
自身授权的访问令牌,那么如果客户端影响其 client_id
或任何其他声明会造成与真实资源所有者混淆,
授权服务器就不应该允许客户端这样做。如果
无法避免这种情况,授权服务器必须提供其他方式,让
资源服务器能够区分这两种访问令牌。¶
授权服务器必须防止攻击者猜测访问 令牌、授权码、刷新令牌、资源所有者 密码和客户端凭据。¶
攻击者猜中生成的令牌(以及其他 非供最终用户处理的凭据)的概率必须小于或 等于 2^(-128),并且应该小于或等于 2^(-160)。¶
授权服务器必须使用其他手段保护 供最终用户使用的凭据。¶
本协议及类似协议的广泛部署可能会使最终用户 对被重定向到要求其输入密码的网站这一做法习以为常。如果最终用户在输入 凭据之前没有 仔细验证这些网站的真实性,攻击者便可能利用这种 做法窃取资源所有者的密码以及其他可通过网络钓鱼获取的 凭据,例如 OTP。¶
服务提供商应该尝试教育最终用户了解 网络钓鱼攻击带来的风险,并应该提供使最终用户能够轻松 确认其网站真实性的机制,例如使用 抗网络钓鱼的认证器,因为只有在 平台成功验证网站来源的情况下,抗网络钓鱼认证器 才会向用户提供用于登录特定网站的凭据。客户端 开发者应该考虑其与用户代理 (例如外部、嵌入式)交互方式的安全影响,以及 最终用户验证授权服务器 真实性的能力。¶
随着授权服务器部署抗网络钓鱼的认证
方法,攻击者可能转而针对授权步骤,
而不是认证步骤。在同意钓鱼攻击中,
攻击者向
授权服务器注册由攻击者控制的客户端,构造一个 scope
值针对受害者资源的授权请求,并通过网络钓鱼消息将生成的
授权端点 URL 发送给受害者。
由于授权请求由合法的
授权服务器处理,资源所有者会正常进行认证,
包括使用任何抗网络钓鱼的因素,然后
会看到一个看似可信的授权提示。
如果资源所有者批准该请求,攻击者就会收到
授权码或访问令牌,从而获得对受害者
资源的访问权限。¶
关键在于,抗网络钓鱼认证器无法防御 同意钓鱼。资源所有者成功向 合法授权服务器进行认证。攻击利用的是 随后的同意步骤,而不是认证步骤。¶
授权服务器应该考虑对客户端 注册实施控制,包括限制特定客户端被 允许请求哪些作用域。在可能的情况下,授权服务器应该 在授予对敏感作用域的访问权限之前验证客户端开发者的身份。¶
授权服务器应该在授权提示期间向资源所有者提供清晰且 有意义的信息,包括 客户端名称、注册它的开发者或组织,以及 所请求的具体作用域,以便资源所有者能够在授予访问权限之前做出 知情决定。在无法预先注册客户端的场景中,例如使用动态客户端注册 [RFC7591] 时, 或者客户端元数据可能由外部方提供, 例如使用客户端 ID 元数据文档 [I-D.ietf-oauth-client-id-metadata-document] 时, 授权服务器应该采取额外措施,以确认 用户理解自己正在授权哪个客户端。¶
授权服务器应该允许管理员和资源所有者 查看已被授予访问其 资源权限的客户端集合,并撤销这些许可(参见 [RFC7009]),从而 在资源所有者受骗批准 恶意授权请求时限制暴露窗口。¶
攻击者可能尝试向受害者设备上 合法客户端的重定向 URI 注入请求,例如使 客户端访问由攻击者控制的资源。这是 一种称为跨站请求伪造(CSRF)的攻击变体。¶
传统对策是客户端在 state 参数中传递一个随机值,
也称为 CSRF 令牌,用于按上述方式将发往
重定向 URI 的请求与用户代理会话关联。该
对策在 第 5.3.5
节
([RFC6819])中进行了详细说明。
code_verifier 参数或
OpenID Connect nonce 值也提供相同的保护。¶
当使用 code_verifier 而不是 state 或
nonce 提供 CSRF 保护时,需要
注意以下几点:¶
客户端必须确保 AS 支持
客户端打算使用的 code_challenge_method。
如果授权服务器不支持所请求的方法,
则必须改用 state 或 nonce 提供 CSRF 保护。¶
如果使用 state 携带应用程序状态,并且
其内容的完整性值得关注,则客户端必须保护 state 防止
篡改和置换。这可以通过将
state 的内容绑定到浏览器会话和/或使用已签名/加密的
state 值 [I-D.bradley-oauth-jwt-encoded-state] 来实现。¶
因此,AS 必须提供一种检测其所支持代码质询 方法的方式, 可以通过按照 [RFC8414] 提供 AS 元数据,或者提供 特定于部署的方式来确保或确定支持情况。¶
如 第 4.4.1.9 节([RFC6819])所述, 授权 请求容易遭受点击劫持攻击,也称为用户 界面伪装。在此类攻击中,攻击者将 授权端点用户界面嵌入一个看似无害的上下文中。 用户以为自己正在与该上下文交互,例如 点击按钮,却无意中与授权 端点用户界面进行了交互。反过来也可以实现: 用户以为自己正在与授权端点交互, 却可能无意中将密码输入到攻击者提供的 覆盖在原始用户界面上的输入字段中。点击劫持 攻击可以设计得使用户几乎察觉不到攻击, 例如使用几乎不可见的 iframe 覆盖在 其他元素之上。¶
攻击者可以利用此向量获取用户的认证 凭据、更改授予客户端的访问作用域, 并可能访问用户的资源。¶
授权服务器必须防止点击劫持攻击。
[RFC6819] 中描述了多种
对策,包括使用
X-Frame-Options HTTP 响应标头字段和破框
JavaScript。除此之外,授权服务器还应该
使用内容安全策略(CSP)第 2 级 [CSP-2] 或更高版本。¶
为了有效,CSP 必须用于授权端点,以及 适用时用于认证用户和 授权客户端的其他端点(例如设备授权端点、登录 页面、错误页面等)。这可以防止支持 CSP 的用户代理中 未经授权的来源进行框架嵌入。客户端可以允许被 与其重定向端点所用来源不同的某些其他来源 进行框架嵌入。因此,授权服务器应该允许 管理员为特定客户端配置允许的来源, 和/或允许客户端动态注册这些来源。¶
使用 CSP 可以让授权服务器在单个响应标头字段中指定多个来源,
并使用灵活的
模式对它们加以限制(详见 [CSP-2])。该标准第 2 级通过结合
限制框架来源的策略(使用 frame-ancestors)
和限制允许在 HTML 页面上执行的脚本来源的策略
(使用 script-src),提供了
防御点击劫持的稳健机制。下面的清单展示了此类策略的一个非规范性
示例:¶
HTTP/1.1 200 OK Content-Security-Policy: frame-ancestors https://ext.example.org:8000 Content-Security-Policy: script-src 'self' X-Frame-Options: ALLOW-FROM https://ext.example.org:8000 ...¶
由于某些用户代理不支持 [CSP-2],因此该技术 应该与其他技术结合使用,包括 [RFC6819] 中描述的技术,除非授权服务器明确 不支持此类旧版用户代理。即使在这种情况下,仍然应该采用其他 对策。¶
当应用程序未经净化地使用输入或其他外部 变量,并导致 应用程序逻辑被修改时,就会发生注入攻击。这可能使攻击者能够 访问应用程序设备或其数据、造成拒绝 服务,或者引入范围广泛的恶意副作用。¶
授权服务器和客户端必须将接收到的参数视为
可能具有恶意的外部输入,并应用适当保护,
尤其是 state 和 redirect_uri 参数的值。¶
开放重定向器是一种端点,它将用户浏览器 转发到从查询参数获得的任意 URI。 有时会实现此类端点,例如先显示一条 消息,然后再将用户重定向到外部网站, 或者在用户被例如登录提示打断后,将用户重定向回其原本打算访问的 URL。¶
当 AS 或客户端具有开放 重定向器时,可能发生以下攻击。¶
客户端不得暴露开放重定向器。攻击者可能使用开放 重定向器生成指向客户端的 URL,并利用它们 外泄授权码,如 第 4.1.1 节([RFC9700])所述。 另一种滥用方式是生成看似指向客户端的 URL。 这可能诱骗用户信任该 URL 并在浏览器中访问它。 这可以被滥用于网络钓鱼。¶
为了防止开放重定向,客户端应该仅在 目标 URL 已列入白名单,或者能够认证请求的来源和完整性时才进行重定向。 OWASP [owasp_redir] 描述了针对开放重定向的对策。¶
在某些部署中,包括使用负载均衡器的部署, 到资源服务器的 TLS 连接会在真正 提供资源的服务器之前终止。这可能使令牌 在 TLS 连接终止的前端服务器与提供资源的后端服务器之间 失去保护。在 此类部署中,必须采用充分措施确保 前端和后 端服务器之间访问令牌的机密性;对令牌进行加密就是一种可行措施。¶
混淆攻击针对 OAuth 客户端与 两个或更多授权服务器交互,且至少一个授权 服务器由攻击者控制的场景。例如, 攻击者可能使用动态注册将 客户端注册到自己的授权服务器,或者某个授权服务器 被攻破。¶
当 OAuth 客户端只能与一个授权服务器交互时,不需要 混淆 防御。但是,在 OAuth 客户端与两个 或更多授权服务器交互的场景中,客户端必须防止混淆攻击。以下 讨论两种不同的方法。¶
对于这两种防御方式,客户端必须为每个授权请求存储其 发送授权请求时对应的发行者,将此信息绑定到 用户代理,并检查授权响应是否来自正确的 发行者。如果适用,客户端必须确保后续访问令牌请求 发送给同一发行者。发行者通过关联的 元数据,充当流程中要使用的授权 端点和令牌端点组合的抽象标识符。如果发行者标识符 不可用,例如既未使用 OAuth 2.0 授权服务器元数据 [RFC8414] 也未使用 OpenID Connect 发现 [OpenID.Discovery],则可以改用此元组的其他唯一标识符 或元组本身。为简化表述, 下文将此类特定于部署的标识符也归入发行者(或 发行者标识符)的概念中。¶
注意:仅存储授权服务器 URL 不足以识别 混淆攻击。攻击者可能将未被攻破的 AS 的授权端点 URL 声明为 “自己的”AS URL,却声明一个由自己控制的令牌端点。¶
有关多种混淆攻击类型的详细说明,请参阅 第 4.4 节([RFC9700])。¶
此防御方式要求客户端比较 授权服务器在授权响应中发送给客户端的发行者标识符值。收到授权 响应时,客户端必须将收到的发行者标识符与已存储的 发行者标识符进行比较。如果不匹配,客户端必须中止 交互。¶
可以通过不同方式将此发行者标识符传输 给客户端:¶
使用 OpenID Connect 且在授权
响应中返回 ID Token 时,客户端可以评估 ID Token 中的 iss 声明。¶
在这两种情况下,都必须按照 [RFC9207] 评估 iss 值。¶
虽然这种防御方式可能需要使用额外参数来 传输 发行者信息,但它是一种稳健且相对简单的混淆攻击防御方式。¶
对于此防御方式,客户端必须为与其交互的每个 发行者 使用不同的重定向 URI。¶
客户端必须通过将发行者对应的不同重定向 URI 与 接收到授权响应的 URI 进行比较,检查授权响应是否 来自正确的 发行者。如果不匹配,客户端 必须中止流程。¶
虽然这种防御方式建立在现有 OAuth 功能之上,但 在客户端仅注册一次便用于多个不同 发行者的场景(例如某些开放银行方案)中无法使用,并且由于它与 客户端注册紧密集成,因此更难以自动部署。¶
此外,攻击者可能能够通过 使用客户端分配给攻击者 AS 的重定向 URI,在“诚实的”AS 上注册一个新客户端,从而绕过 此防御提供的保护。然后攻击者可以像上面所述那样运行 攻击,将 客户端 ID 替换为其新创建客户端的客户端 ID。¶
因此,只有在其他选项不可用时才应该使用此防御方式。¶
原生应用程序是安装并执行在资源所有者所使用设备上的客户端 (即桌面应用程序或原生移动 应用程序)。原生应用程序需要在 安全性、平台能力和整体最终用户 体验方面给予特殊考虑。¶
本节中的指南主要针对原生移动应用, 而不是桌面应用。就为应用开发者提供的 与此处所述 OAuth 流程相关的能力而言,原生移动平台 比桌面平台更加成熟。虽然 本指南主要关注移动应用,但其中许多内容通常也 适用于桌面应用。¶
授权端点要求客户端 与资源所有者的用户代理之间进行交互。当前最佳实践是 在外部用户代理 (通常是浏览器)中执行 OAuth 授权请求,而不是在嵌入式用户代理(例如 使用 WebView 实现的用户代理)中执行。¶
原生应用程序可以通过多种不同方式捕获来自 授权服务器的响应, 每种方式具有不同的安全属性。例如,使用带有 “应用声明 URL”的重定向 URI,或使用 在操作系统中注册的自定义 URL 方案以调用 客户端作为处理程序,手动复制粘贴凭据, 运行本地 Web 服务器,安装用户代理扩展,或者 提供一个标识由客户端控制的服务器托管 资源的重定向 URI,而该资源又将 响应提供给原生应用程序。¶
过去,原生应用通常会使用嵌入式用户代理 (通常通过 WebView 实现)来处理 OAuth 授权 请求。这种方法存在许多缺点,包括宿主应用 能够复制用户凭据和 Cookie,以及用户 需要在每个应用中从头进行认证。有关使用嵌入式用户代理 处理 OAuth 的缺点的更深入分析,请参阅第 8.5.1 节。¶
使用系统浏览器的原生应用授权请求更加 安全,并且可以利用用户在设备上的认证状态。 能够使用浏览器中的现有认证会话 可以实现单点登录,因为用户无需在每次使用新应用时都向 授权服务器进行认证(除非 授权服务器策略要求这样做)。¶
无需更改 OAuth 协议本身即可支持原生应用与浏览器之间的授权流程, 因为 OAuth 授权请求和响应已经通过 URI 定义。这包括可用于应用间 通信的 URI。某些假定所有 客户端都是机密 Web 客户端的 OAuth 服务器实现,需要增加对 公共原生应用客户端以及它们所使用重定向 URI 类型的理解,以支持此最佳实践。¶
作为分发给多个用户的应用的一部分静态包含的秘密
并不是机密秘密,因为一个
用户可以检查其副本并得知共享秘密。基于此
原因,授权服务器不得要求原生应用客户端使用共享秘密进行客户端
认证,
因为除了客户端标识之外,这并没有提供额外价值,而客户端标识
已由 client_id 请求参数提供。¶
仍然要求原生应用客户端使用静态包含的共享 秘密的授权服务器,必须将该客户端视为公共 客户端(如第 2.1 节所定义),并且 不得 将该秘密视为客户端身份的证明。如果没有 额外措施,此类客户端容易遭受客户端冒充 (参见第 7.3.1 节)。¶
除非使用类似动态客户端注册 [RFC7591] 的机制来为 每个实例配置凭据,否则原生应用 被分类为公共客户端,如第 2.1 节所定义, 并且必须以此身份在授权服务器处注册。 授权服务器必须在客户端注册详细信息中记录客户端类型, 以便识别并相应地处理请求。¶
草案规范 [I-D.ietf-oauth-attestation-based-client-auth] 定义了一种原生应用可用于获取 密钥绑定证明的机制,以向授权服务器或 资源服务器进行认证。这可以为 移动应用的身份提供更高程度的保证。¶
正如在 Web 上使用 URI 进行 OAuth 以发起 授权请求并将授权响应返回给 请求网站一样,原生应用也可以使用 URI 在设备浏览器中发起 授权请求,并将 响应返回给发起请求的原生应用。¶
通过采用 Web 上用于 OAuth 的相同方法, Web 上获得的优势,例如单点登录会话的易用性和 独立认证上下文的安全性,同样可以在 原生应用环境中获得。复用相同方法还可以 降低实现复杂度并提高互操作性,因为它 依赖基于标准的 Web 流程,而不是特定于某个 平台。¶
原生应用必须使用外部 用户代理来执行 OAuth 授权请求。这通过 在浏览器中打开授权请求(详见 第 8.3 节),并 使用能够将 授权响应返回给原生应用的重定向 URI(定义于第 8.4 节)来实现。¶
嵌入式用户代理在技术上可以用于授权原生 应用。根据定义,这些嵌入式用户代理对于授权服务器的第三方而言并不安全, 因为托管 嵌入式用户代理的应用可以访问用户完整的认证 凭据,而不仅仅是原本授予 该应用的 OAuth 授权许可。它们通常还会受到操作系统 的沙箱限制,并且依赖 Web 来源的 WebAuthn 等机制会被禁用。¶
在典型的基于 WebView 的嵌入式用户代理实现中, 宿主应用程序可以记录登录 表单中输入的每次按键以捕获用户名和密码,自动提交表单 以绕过用户同意,并复制会话 Cookie,使用它们 以用户身份执行经过认证的操作。¶
即使由与 授权服务器属于同一方的受信任应用使用,嵌入式用户代理也违反最小 权限原则,因为它们可以访问比 实际所需更强大的凭据,从而可能扩大攻击面。¶
鼓励用户在没有浏览器通常具有的地址栏和可见证书验证 功能的嵌入式用户代理中输入凭据, 会使用户无法知道 自己是否正在登录合法网站;即使确实如此,这也会 训练用户认为无需先验证网站便输入凭据是可以接受的。¶
除了安全问题之外,嵌入式用户代理不会与其他应用或浏览器共享 认证状态,因此 用户必须为每个授权请求登录,这通常 被认为是较差的用户体验。¶
发起授权请求的原生应用对 用户界面具有很大程度的控制权,并可能 呈现伪造的外部用户代理,即 被伪装成外部用户代理的嵌入式用户代理。¶
当所有良性参与方都使用外部用户代理时,其优势 在于安全专家能够检测恶意参与方,因为 任何伪造外部用户代理的行为都可以被证明是恶意的。另一方面, 如果良性和恶意参与方都使用嵌入式用户代理, 恶意参与方无需伪造任何东西,因此更难被发现。 一旦检测到恶意应用,就可能利用这些 信息在恶意软件扫描 软件中将应用签名列入黑名单、执行移除操作(对于由应用 商店分发的应用)以及采取其他措施来减少 恶意应用的影响和传播。¶
授权服务器还可以通过要求一种仅真正的外部 用户代理可用的认证因素,直接防御伪造的外部 用户代理。¶
在使用应用内浏览器标签页时特别关注自身安全的用户, 还可以采取额外步骤,从应用内浏览器标签页中 在完整浏览器里打开请求,并在那里完成 授权,因为大多数应用内 浏览器标签页模式的实现都提供此功能。¶
如果恶意应用能够将自己配置为操作系统中
https 方案 URI 的默认处理程序,
它就能够
拦截使用默认浏览器的授权请求,并
滥用这一受信任位置实施网络钓鱼等恶意行为。¶
这种攻击并不限于 OAuth;以
此方式配置的恶意应用会给用户带来一种超出
原生应用 OAuth 使用范围的普遍且持续的风险。许多操作系统通过
要求用户执行明确操作才能更改
http 和 https 方案 URI 的默认处理程序来缓解此
问题。¶
基于浏览器的应用是在 Web 浏览器中运行的客户端,通常 使用 JavaScript 编写,也称为“单页应用”。此类应用 具有与原生应用类似的特殊安全注意事项。¶
待办:在基于浏览器的应用 BCP 最终定稿后,引入其中的规范性文本。¶
本草案整合了 OAuth 2.0 [RFC6749]、 原生应用的 OAuth 2.0 [RFC8252]、 代码交换证明密钥 [RFC7636]、 基于浏览器的应用的 OAuth 2.0 [I-D.ietf-oauth-browser-based-apps]、 OAuth 安全最佳当前实践 [RFC9700] 以及持有者令牌用法 [RFC6750]中的功能。¶
如果后续草案更新或废止了原始 [RFC6749] 中的功能,则本草案中的该功能会 根据后续草案所述的规范性 更改进行更新,或者被完全移除。¶
下面列出了与 OAuth 2.0 相比的非规范性更改列表:¶
授权码许可使用 PKCE [RFC7636] 中的功能进行了扩展, 因此按照本规范使用授权码许可的默认方式 要求添加 PKCE 参数¶
按照 第 4.14.2 节([RFC9700]),公共客户端的刷新令牌必须是发送方约束的或 一次性使用的¶
包含授权码的令牌端点请求不再
包含
redirect_uri 参数¶
授权服务器必须支持在请求正文中包含客户端凭据¶
移除了 PKCE plain 方法¶
OAuth 2.0 隐式许可已从 OAuth 2.1 中省略,因为它已在 [RFC9700] 中被弃用。¶
移除隐式许可的目的是不再在授权响应中颁发访问令牌,
因为此类令牌容易遭到泄露
和注入,并且无法对客户端施加发送方约束。
客户端通过使用 response_type=token 参数来指示此行为。
OAuth 2.1 中不再定义 response_type 参数的此值。¶
移除 response_type=token 不会影响其他
从授权端点返回其他工件的扩展
响应类型,例如 [OpenID.Connect] 定义的
response_type=id_token。¶
在 OAuth 2.0 中,授权码
流程中的令牌端点请求(第
4.1.3 节([RFC6749]))包含一个
可选的 redirect_uri 参数。该参数旨在防止
授权码注入攻击,并且如果原始授权请求中发送了 redirect_uri 参数,
则必须包含该参数。只有在为特定
客户端注册了多个重定向 URI 时,授权请求才要求
redirect_uri 参数。然而在实践中,许多授权服务器实现即使只注册了一个重定向 URI,
也要求授权请求包含
redirect_uri 参数,从而导致令牌端点
同样要求 redirect_uri 参数。¶
在 OAuth 2.1 中,授权码注入由
code_challenge 和 code_verifier 参数防止,因此在令牌请求中包含
redirect_uri 参数不再具有作用。因此,该参数已被移除。¶
为了使希望同时支持
OAuth 2.0 和 OAuth 2.1 客户端的授权服务器保持向后兼容,授权服务器必须允许客户端在
令牌请求(第 4.1.3 节)中发送
redirect_uri 参数,并且必须按照
[RFC6749] 中所述强制执行该参数。授权服务器可以
使用请求中的 client_id 来确定是否对
已知将使用旧版 OAuth 2.0 行为的特定客户端强制执行此行为。¶
仅遵循 OAuth 2.1 建议的客户端不会在
令牌请求中发送 redirect_uri,因此它将无法与
期望令牌请求中包含该参数的授权服务器兼容。¶
本节使用 [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¶
client-id = *VSCHAR¶
client_secret 元素定义于第 2.4.1 节:¶
client-secret = *VSCHAR¶
response_type 元素定义于第 4.1.1 节和第 6.4 节:¶
response-type = response-name *( SP response-name ) response-name = 1*response-char response-char = "_" / DIGIT / ALPHA¶
scope = scope-token *( SP scope-token ) scope-token = 1*NQCHAR¶
state 元素定义于第 4.1.1 节、第 4.1.2 节以及第 4.1.2.1 节:¶
state = 1*VSCHAR¶
error 元素定义于第 4.1.2.1 节、第 3.2.4 节
和第 5.3 节:¶
error = 1*NQSCHAR¶
error_description 元素定义于第 4.1.2.1 节、
第 3.2.4 节和第 5.3 节:¶
error-description = 1*NQSCHAR¶
error_uri 元素定义于第 4.1.2.1 节、第 3.2.4 节
和第 5.3 节:¶
error-uri = URI-reference¶
grant-type = grant-name / URI-reference grant-name = 1*name-char name-char = "-" / "." / "_" / DIGIT / ALPHA¶
access-token = 1*VSCHAR¶
token_type 元素定义于第 3.2.3 节和第 6.1 节:¶
token-type = type-name / URI-reference type-name = 1*name-char name-char = "-" / "." / "_" / DIGIT / ALPHA¶
expires-in = 1*DIGIT¶
code_verifier 的 ABNF 如下。¶
code-verifier = 43*128unreserved unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" ALPHA = %x41-5A / %x61-7A DIGIT = %x30-39¶
code_challenge 的 ABNF 如下。¶
code-challenge = 43*128unreserved unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" ALPHA = %x41-5A / %x61-7A DIGIT = %x30-39¶
在 [RFC6749] 发布时,
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(空格)、(2) U+0025(百分号)、 (3) U+0026(与号)、(4) U+002B(加号)、 (5) U+00A3(英镑符号)以及 (6) U+20AC(欧元符号),将被编码 为下面的八位字节序列(使用十六进制表示法):¶
20 25 26 2B C2 A3 E2 82 AC¶
然后在内容中表示为:¶
+%25%26%2B%C2%A3%E2%82%AC¶
本规范中的各种消息使用下面所述方法之一进行序列化。 本节说明这些序列化方法的语法;其他章节说明 何时可以以及必须使用它们。请注意,并非所有方法都能用于所有消息。¶
为了使用查询字符串序列化对参数进行序列化, 客户端使用 [WHATWG.URL] 定义的 application/x-www-form-urlencoded 格式,将参数和值添加到 URL 的查询组成部分中来构造字符串。查询字符串序列化 通常用于 HTTP GET 请求。¶
下面列出发布时已广泛确立的扩展:¶
令牌撤销扩展定义了一种机制,使客户端能够 向授权服务器表明某个访问令牌不再需要。¶
动态客户端注册提供了一种 以编程方式向授权服务器注册客户端的机制。¶
令牌内省扩展定义了一种 资源服务器获取访问令牌相关信息的机制。¶
授权服务器元数据(也称为 OAuth 发现) 定义了一个端点,客户端可以使用该端点查找与特定 OAuth 服务器交互所需的信息,例如授权端点和令牌端点的位置 以及支持的许可类型。¶
设备授权许可(以前称为设备 流程)是一种扩展,使没有浏览器或输入能力有限的设备 能够获取访问令牌。它通常用于智能电视应用,或 硬件视频编码器之类能够将视频流式传输到流媒体视频服务的设备。¶
相互 TLS 描述了一种通过 TLS 证书认证将令牌绑定到其所颁发给的客户端的机制,以及一种客户端认证机制。¶
提供一种方式,使客户端能够明确向 授权服务器表明其打算在哪里使用正在请求的访问令牌。¶
[RFC9068]:OAuth 2.0 访问令牌的 JSON Web Token(JWT)配置文件¶
本规范定义了一个以 JSON Web Token(JWT)格式颁发 OAuth 访问 令牌的配置文件。¶
推送授权请求扩展描述了一种 从后通道发起 OAuth 流程的技术,为构建复杂授权请求提供更好的安全性 和更大的灵活性。¶
授权响应中的 iss 参数
指明授权服务器的身份,以防止客户端中的混淆攻击。¶
丰富授权请求规定了一个新参数
authorization_details,用于在 OAuth 授权请求中携带细粒度授权数据。¶
DPoP 描述了一种通过应用程序层的持有证明机制 对 OAuth 2.0 令牌施加发送方约束的机制。¶
逐步增强认证描述了一种机制,资源服务器可以 使用该机制向客户端表明,与当前请求的访问令牌关联的认证事件 不满足其认证要求。¶
本规范是 OAuth 工作组的成果,其起点 基于以下规范的内容:OAuth 2.0 授权框架(RFC 6749)、 原生应用的 OAuth 2.0(RFC 8252)、OAuth 安全最佳当前实践以及基于浏览器的应用的 OAuth 2.0。 编辑者谨向所有参与创建这些 本规范所基于规范的人士表示感谢。¶
编辑者还要感谢以下人士提供的想法、 反馈、更正和措辞,这些贡献帮助塑造了本版规范:Andrii Deinega、 Bob Hamburg、Brian Campbell、Daniel Fett、Deng Chao、Emelia Smith、Falko、Filip Skokan、Goutam Adwant、 Joseph Heenan、Justin Richer、Karsten Meyer zu Selhausen、Michael Jones、Michael Peck、Roberto Polli、 Tim Würtele 和 Vittorio Bertocci。¶
围绕本规范的讨论还曾在 2021 年和 2022 年的 OAuth 安全研讨会上 进行。作者感谢研讨会组织者(Guido Schmitz、Steinar Noem 和 Daniel Fett)举办了一个有利于协作和社区意见交流的活动。¶
[[ 将从最终规范中移除 ]]¶
-16¶
移除 PKCE plain 方法¶
在授权端点定义章节中提及 PAR¶
添加有关 OAuth 同意钓鱼的安全注意事项章节¶
要求 AS 必须发送 iss 响应参数(仍允许
客户端选择混淆攻击缓解方式)¶
将有关值长度的文本整合到新的“值的大小” 章节中¶
澄清授权端点错误响应行为¶
-15¶
为 JWT 客户端认证添加更多上下文,并明确 建议 RFC7523bis¶
编辑性澄清和更新¶
澄清授权端点和令牌端点中的错误响应¶
同步 RFC9700 中有关 AS 开放重定向注意事项的措辞¶
应用 RFC6750 勘误 3500 和 6613¶
解决重复参数方面的歧义¶
-14¶
编辑性澄清¶
更正一处“依赖方”与“资源服务器”的用词¶
添加对 RFC7591 中 client_secret_post 和
client_secret_basic 术语的引用¶
将“净化”的措辞替换为将其视为不受信任的输入¶
澄清原生应用指南主要适用于移动应用 平台¶
澄清不存在要求 AS 必须特别支持公共或 机密客户端¶
-13¶
-12¶
更新客户端注册相关措辞,以更好地反映 OpenID Federation 和开放生态系统中使用的替代注册方法¶
在扩展附录中添加 DPoP 和逐步增强认证¶
将认证方案大小写不敏感的引用更新为 HTTP,而不是 ABNF¶
更正一处“依赖方”与“客户端”的用词¶
将 client_id 要求移到各个许可类型中¶
将序列化方法的说明整合到附录中¶
-11¶
-10¶
澄清客户端 ID 是不透明字符串¶
扩展可以为资源请求定义其他错误代码¶
改进错误字段定义的格式¶
将“scope”定义移到简介章节并扩展¶
将访问令牌章节拆分为结构和请求¶
将 b64token 重命名为 token68,以与 RFC7235 保持一致¶
恢复旧附录 B 中有关 application/x-www-form-urlencoded 的内容¶
澄清客户端不得解析访问令牌¶
扩展关于授权请求中何时需要 redirect_uri 参数的文本¶
为保持一致,在刷新令牌章节中将“permissions”改为“privileges”¶
整合授权码流程安全注意事项¶
澄清授权码重用——一个授权码只能 获取一次访问令牌¶
-09¶
AS 不得在授权端点支持 CORS 请求¶
增加关于非对称客户端认证的细节¶
从安全 BCP 同步 CSRF 说明¶
更新并移动发送方约束的访问令牌章节¶
从安全 BCP 同步客户端冒充资源所有者的内容¶
在重定向 URI 注册章节中添加对授权请求的引用¶
从安全 BCP 同步刷新令牌轮换章节¶
从安全 BCP 同步重定向 URI 匹配文本¶
更新对 RAR(RFC9396)的引用¶
澄清 URI¶
从令牌请求中移除 redirect_uri¶
扩展 code_verifier 相关安全注意事项¶
修订简介章节¶
-08¶
更新致谢¶
在客户端 ID 定义中将“由受信任方”替换为“由外部方”¶
将“验证资源所有者的身份”替换为“认证”¶
澄清刷新令牌轮换以与 RFC6819 保持一致¶
添加用于存放 application/x-www-form-urlencoded 示例的附录¶
修复对附录条目的引用¶
纳入安全 BCP 中新的“通过 AS 进行网络钓鱼”章节¶
重新表述客户端认证动机的说明¶
将令牌请求中的“scope”参数移到特定许可类型中,以 与 OAuth 2.0 保持一致¶
根据最新版安全 BCP 更新点击劫持和开放重定向说明¶
将规范性要求移出授权码安全 注意事项章节¶
澄清安全注意事项,并移除重复章节¶
-07¶
从摘要中移除“第三方”¶
在简介中添加 MFA 和无密码认证作为额外动机¶
提及 PAR 是进行重定向 URI 注册的一种方式¶
添加要求令牌端点使用 CORS 标头的引用¶
更新对 OMAP 扩展的引用¶
修复序列图中的编号¶
-06¶
移除“有凭据客户端”术语¶
简化“机密”和“公共”客户端的定义¶
纳入引用 RFC9207 的 iss 响应参数¶
添加关于 RS 验证访问令牌的章节¶
移除授权服务器必须支持原生应用全部 3 种重定向 方法的要求¶
修复部分引用¶
将 HTTP 引用更新为 RFC 9110¶
澄清“授权许可”术语¶
澄清客户端凭据许可的使用¶
整理授权码图示¶
更新 application/x-www-form-urlencoded 的引用,并移除 关于其不在 IANA 注册表中的过时说明¶
-05¶
添加关于移除隐式流程的章节¶
将许多规范性要求从安全注意事项移到 相应的正文章节¶
重新组织并整合 TLS 相关措辞¶
除 localhost/自定义 URL 方案外,要求重定向 URI 使用 TLS¶
更新刷新令牌指南以与安全 BCP 保持一致¶
-04¶
-03¶
重构,将所有许可类型集中到第 4 节同一顶级标题下¶
更好地区分规范性文本和安全注意事项文本并放到 适当位置,既将实际上属于安全注意事项的文本移出文档正文, 也将规范性要求从安全注意事项 章节移入正文的适当位置¶
纳入 RFC6749 已发布的许多勘误¶
更新对各种 RFC 的引用¶
全文编辑性澄清¶
-02¶
-01¶
-00¶
初始修订版¶