OAuth 2.0 协议速查表¶
本速查表介绍了 OAuth 2.0 的最佳当前安全实践,这些实践源自其 RFC。OAuth 已成为 API 保护的标准,也是使用 OpenID Connect 进行联邦登录的基础。OpenID Connect 1.0 是一个基于 OAuth 2.0 协议的简单身份层。它使客户端能够根据授权服务器执行的身份验证来验证最终用户的身份,并以可互操作的、类似 REST 的方式获取有关最终用户的基本个人资料信息。
术语¶
- 访问令牌 = 提供一种抽象,用资源服务器可以理解的单个令牌替代不同的授权结构(例如,用户名和密码,断言)。这种抽象使得可以颁发短期有效的访问令牌,并消除了资源服务器需要理解各种身份验证方案的需求。
- 刷新令牌 = 是用于获取访问令牌的凭据。这些令牌由授权服务器颁发给客户端,用于在当前访问令牌失效或过期时获取新的访问令牌,或获取具有相同或更窄范围的额外访问令牌(访问令牌的有效期可能比资源所有者授权的权限更短且权限更少)。
- 客户端 = 通常指代表资源所有者并在其授权下发出受保护资源请求的应用程序。“客户端”一词不暗示任何特定的实现特征(例如,应用程序是在服务器、桌面还是其他设备上执行)。
- 授权服务器 (AS) = 指成功验证资源所有者并获得授权后向客户端颁发访问令牌的服务器。
- 资源所有者 (RO) = 指能够授予受保护资源访问权限的实体。当资源所有者是人时,则称为最终用户。
- 资源服务器 (RS) = 指托管受保护资源的服务器,能够使用访问令牌接受并响应受保护资源请求。
OAuth 2.0 基本要点¶
- 客户端和授权服务器不得暴露将用户浏览器转发到从查询参数(“开放重定向器”)获取的任意 URI 的 URL,这可能导致授权码和访问令牌的泄露。
- 已确保授权服务器支持 PKCE 的客户端可以依赖 PKCE 提供的 CSRF 保护。在 OpenID Connect 流程中,“nonce”参数提供 CSRF 保护。否则,必须使用“state”参数中携带的一次性用户 CSRF 令牌进行 CSRF 保护,这些令牌必须安全地绑定到用户代理。
- 当 OAuth 客户端可以与多个授权服务器交互时,客户端应使用颁发者“iss”参数作为对策,或者根据授权响应中的“iss”值(例如 OpenID 中 ID Token 的“iss”声明)进行判断。
- 当 OAuth 客户端与多个授权服务器交互的其他对策选项缺失时,客户端可以转而使用不同的重定向 URI 来识别授权端点和令牌端点。
- 授权服务器应避免意外转发或重定向可能包含用户凭据的请求。
PKCE - 授权码交换验证码机制¶
使用授权码授权(Authorization Code Grant)的 OAuth 2.0 公共客户端容易受到授权码拦截攻击。授权码交换验证码 (PKCE,发音为“pixy”) 是用于缓解授权码拦截攻击威胁的技术。
最初,PKCE 旨在专门用于保护原生应用程序,但后来它成为了一项已部署的 OAuth 功能。它不仅能防御授权码注入攻击,还能保护为公共客户端创建的授权码,因为 PKCE 确保攻击者在不知道 `code_verifier` 的情况下无法在授权服务器的令牌端点兑换被盗的授权码。
- 客户端通过使用 PKCE 流程来防止授权码注入(重放)到授权响应中。此外,客户端也可以使用 OpenID Connect 的“nonce”参数和 ID Token 中相应的声明。PKCE 挑战或 OpenID Connect 的“nonce”必须是特定于事务的,并安全地绑定到客户端以及启动该事务的用户代理。
- 使用 PKCE 时,客户端应使用不会在授权请求中暴露 PKCE 验证器(PKCE verifier)的 PKCE 代码挑战方法。否则,能够读取授权请求的攻击者可能会破坏 PKCE 提供的安全性。授权服务器必须支持 PKCE。
- 如果客户端在授权请求中发送了有效的 PKCE “code_challenge” 参数,授权服务器会在令牌端点强制执行 “code_verifier” 的正确使用。
- 授权服务器通过确保仅当授权请求中存在“code_challenge”参数时才接受包含“code_verifier”参数的令牌请求,从而缓解 PKCE 降级攻击。
隐式授权¶
隐式授权是一种简化的授权码流程,针对使用 JavaScript 等脚本语言在浏览器中实现的客户端进行了优化。在隐式流程中,授权服务器不向客户端颁发授权码,而是直接向客户端颁发访问令牌(作为资源所有者授权的结果)。这种授权类型是隐式的,因为没有颁发中间凭据(如授权码)(随后用于获取访问令牌)。
- 客户端使用响应类型“code”(即授权码授权类型)或任何其他导致授权服务器在令牌响应中颁发访问令牌的响应类型,例如“code id_token”响应类型。这使得授权服务器能够检测攻击者的重放尝试,并且由于访问令牌不会在 URL 中暴露,因此通常会减少攻击面。它还允许授权服务器对颁发的令牌进行发送方限制。
令牌重放攻击防护¶
- 授权服务器和资源服务器正在使用发送方限制访问令牌的机制来防止令牌重放,例如 OAuth 2.0 的相互 TLS 或 OAuth 所有权证明(DPoP)。
- 刷新令牌应进行发送方限制或使用刷新令牌轮换。
访问令牌权限限制¶
- 与访问令牌关联的权限应限制在特定应用程序或用例所需的最低限度。这可以防止客户端超出资源所有者授权的权限。它还可以防止用户超出各自安全策略授权的权限。权限限制还有助于减少访问令牌泄露的影响。
- 访问令牌应限制用于特定的资源服务器(受众限制),最好是单个资源服务器。授权服务器应将访问令牌与特定的资源服务器关联起来,并且每个资源服务器都有义务对每个请求进行验证,以确定随该请求发送的访问令牌是否旨在用于该特定的资源服务器。如果不是,资源服务器必须拒绝处理相应的请求。客户端和授权服务器可以分别利用“scope”和“resource”参数来确定他们想要访问的资源服务器。
- 访问令牌应限制用于资源服务器或资源上的特定资源和操作。授权服务器应将访问令牌与相应的资源和操作关联起来,并且每个资源服务器都有义务对每个请求进行验证,以确定随该请求发送的访问令牌是否旨在用于特定资源上的特定操作。如果不是,资源服务器必须拒绝处理相应的请求。客户端和授权服务器可以利用“scope”和“authorization_details”参数来确定这些资源和/或操作。
资源所有者密码凭据授权¶
- 不应使用资源所有者密码凭据授权。这种授权类型不安全地将资源所有者的凭据暴露给客户端,增加了应用程序的攻击面。
客户端认证¶
- 授权服务器应尽可能使用客户端认证。建议使用非对称(基于公钥)方法进行客户端认证,例如 mTLS 或“private_key_jwt”(OpenID Connect)。当使用非对称方法进行客户端认证时,授权服务器无需存储敏感的对称密钥,这使得这些方法更能抵御多种攻击。
其他建议¶
- 授权服务器不允许客户端影响其“client_id”或“sub”值或任何其他可能与真实资源所有者混淆的声明(Claim)。建议使用端到端 TLS。
- 授权响应不得通过未加密的网络连接传输。授权服务器不得允许使用“http”方案的重定向 URI,使用环回接口重定向(Loopback Interface Redirection)的原生客户端除外。
参考资料