1. Introduction
-
简介
在传统的客户端-服务器认证模型中, 客户端通过使用资源所有者的凭据向服务器认证, 来请求服务器上受访问限制的资源 (受保护资源). 为了让第三方应用程序能够访问受限资源, 资源所有者会与第三方共享其凭据. 这会带来若干问题和限制:
o 第三方应用程序必须保存资源所有者的凭据以供将来使用, 通常是明文密码.
o 即使密码自身存在固有安全弱点, 服务器仍必须支持密码认证.
o 第三方应用程序会获得对资源所有者受保护资源的过宽访问权限, 使资源所有者无法限制访问期限, 也无法仅授权访问资源的有限子集.
o 资源所有者无法只撤销某个第三方的访问权限而不影响其他第三方, 并且只能通过修改第三方使用的密码来完成撤销.
o 任何第三方应用程序一旦被攻破, 都会导致最终用户密码以及该密码所保护的全部数据被攻破.
OAuth 通过引入授权层并分离客户端与资源所有者的角色来解决这些问题. 在 OAuth 中, 客户端请求访问由资源所有者控制并托管在资源服务器上的资源, 并获得一组不同于资源所有者凭据的凭据.
客户端并不使用资源所有者的凭据来访问受保护资源, 而是获得访问令牌 (access token), 即一个表示特定作用域, 生命周期以及其他访问属性的字符串. 授权服务器在资源所有者批准后向第三方客户端签发访问令牌. 客户端使用该访问令牌访问托管在资源服务器上的受保护资源.
例如, 最终用户 (资源所有者) 可以授权打印服务 (客户端) 访问其存储在照片共享服务 (资源服务器) 中的受保护照片, 而不必把用户名和密码分享给打印服务. 相反, 她直接向照片共享服务信任的服务器 (授权服务器) 认证, 该服务器向打印服务签发特定于委托的凭据 (访问令牌).
本规范设计用于 HTTP ([RFC2616]). 在 HTTP 以外的任何协议上使用 OAuth 均不在本规范范围内.
OAuth 1.0 协议 ([RFC5849]) 作为信息性文档发布, 是一个小型临时社区工作的成果. 本标准轨规范建立在 OAuth 1.0 的部署经验之上, 也吸收了更广泛 IETF 社区收集到的其他用例和可扩展性需求. OAuth 2.0 协议不向后兼容 OAuth 1.0. 两个版本可以在网络中共存, 实现也可以选择同时支持二者. 但是, 本规范的意图是新的实现按照本文档所规定的方式支持 OAuth 2.0, 而 OAuth 1.0 仅用于支持既有部署. OAuth 2.0 协议与 OAuth 1.0 协议几乎不共享实现细节. 熟悉 OAuth 1.0 的实现者应当在阅读本文档时不预设其结构和细节.
1.1. 角色
OAuth 定义了四种角色:
resource owner 能够授予对受保护资源访问权限的实体. 当资源所有者是个人时, 称为最终用户.
resource server 托管受保护资源的服务器, 能够使用访问令牌接受并响应受保护资源请求.
client 代表资源所有者并经其授权发起受保护资源请求的应用程序. "client" 一词并不暗示任何特定实现特征, 例如应用程序是在服务器, 桌面还是其他设备上执行.
authorization server 在成功认证资源所有者并获得授权后, 向客户端签发访问令牌的服务器.
授权服务器与资源服务器之间的交互不在本规范范围内. 授权服务器可以与资源服务器是同一台服务器, 也可以是独立实体. 单个授权服务器可以签发被多个资源服务器接受的访问令牌.
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 ---| |
+--------+ +---------------+
Figure 1: Abstract Protocol Flow
图 1 所示的抽象 OAuth 2.0 流程描述了四种角色之间的交互, 包括以下步骤:
(A) 客户端向资源所有者请求授权. 授权请求可以直接发给资源所有者 (如图所示), 也可以, 并且更推荐, 通过授权服务器作为中介间接发起.
(B) 客户端收到授权许可 (authorization grant). 这是表示资源所有者授权的一种凭据, 使用本规范定义的四种许可类型之一表示, 也可以使用扩展许可类型表示. 授权许可类型取决于客户端请求授权所采用的方法以及授权服务器支持的类型.
(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 +---------------+
Figure 2: Refreshing an Expired Access Token
图 2 所示流程包括以下步骤:
(A) 客户端通过向授权服务器认证并提交授权许可来请求访问令牌.
(B) 授权服务器认证客户端并验证授权许可, 如果有效, 则签发访问令牌和刷新令牌.
(C) 客户端通过提交访问令牌向资源服务器发起受保护资源请求.
(D) 资源服务器验证访问令牌, 如果有效, 则为该请求提供服务.
(E) 步骤 (C) 和 (D) 重复进行, 直到访问令牌过期. 如果客户端知道访问令牌已经过期, 则跳到步骤 (G); 否则, 它发起另一个受保护资源请求.
(F) 由于访问令牌无效, 资源服务器返回无效令牌错误.
(G) 客户端通过向授权服务器认证并提交刷新令牌来请求新的访问令牌. 客户端认证要求基于客户端类型和授权服务器策略.
(H) 授权服务器认证客户端并验证刷新令牌, 如果有效, 则签发新的访问令牌, 并且可以选择签发新的刷新令牌.
如第 7 节所述, 步骤 (C), (D), (E) 和 (F) 不在本规范范围内.
1.6. TLS 版本
每当本规范使用传输层安全 (Transport Layer Security, TLS) 时, 合适的 TLS 版本会随着时间变化, 取决于广泛部署情况和已知安全漏洞. 在撰写本文时, TLS 1.2 版 [RFC5246] 是最新版本, 但部署基础非常有限, 可能不容易用于实现. TLS 1.0 版 [RFC2246] 是部署最广泛的版本, 将提供最广泛的互操作性.
实现也可以支持满足其安全需求的其他传输层安全机制.
1.7. HTTP 重定向
本规范广泛使用 HTTP 重定向, 即客户端或授权服务器将资源所有者的用户代理定向到另一个目标. 虽然本规范中的示例展示了 HTTP 302 状态码的用法, 但也允许使用用户代理可用的任何其他方法来完成这种重定向, 并将其视为实现细节.
1.8. 互操作性
OAuth 2.0 提供了一个具有明确定义安全属性的丰富授权框架. 然而, 作为一个包含许多可选组件的丰富且高度可扩展的框架, 本规范本身很可能产生大量互不兼容的实现.
此外, 本规范还将若干必需组件部分或完全留作未定义 (例如客户端注册, 授权服务器能力, 端点发现). 缺少这些组件时, 为了实现互操作, 客户端必须针对特定授权服务器和资源服务器进行手工且专门的配置.
该框架的设计明确预期未来工作将定义规范性配置文件和扩展, 以实现完整的 Web 规模互操作性.
1.9. 表示约定
本规范中的关键词 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY" 和 "OPTIONAL" 应按 [RFC2119] 中的描述解释.
本规范使用 [RFC5234] 的增强巴科斯-瑙尔范式 (Augmented Backus-Naur Form, ABNF) 表示法. 此外, 规则 URI-reference 引自 "Uniform Resource Identifier (URI): Generic Syntax" [RFC3986].
某些与安全相关的术语应按 [RFC4949] 中定义的含义理解. 这些术语包括但不限于 "attack", "authentication", "authorization", "certificate", "confidentiality", "credential", "encryption", "identity", "sign", "signature", "trust", "validate" 和 "verify".
除非另有说明, 所有协议参数名称和值都区分大小写.