跳到主要内容

5. 安全考虑

由于发送到客户端注册端点的请求会导致明文凭据被传输 (在 HTTP 请求和响应中), 授权服务器在向注册端点发送请求时必须要求使用传输层安全机制. 服务器必须支持 TLS 1.2 [RFC5246], 也可以支持满足其安全要求的其他传输层安全机制. 使用 TLS 时, 客户端必须按照 RFC 6125 [RFC6125] 执行 TLS/SSL 服务器证书检查. 实现层面的安全考虑见 Recommendations for Secure Use of TLS and DTLS [BCP195].

对于使用基于重定向的授权类型 (例如 "authorization_code""implicit") 的客户端, 授权服务器必须要求客户端注册其重定向 URI 值. 这有助于缓解恶意行为者注入并模拟已合法注册客户端, 并通过无效重定向 URI 或开放重定向器截获其授权码或令牌的攻击. 此外, 为了防止重定向返回值被劫持, 注册的重定向 URI 值必须属于以下之一:

  • 受 TLS 保护的远程网站 (例如 https://client.example.com/oauth_redirect)
  • 使用 HTTP URI 托管在本机上的网站 (例如 http://localhost:8080/oauth_redirect)
  • 只对客户端应用可用的非 HTTP 应用专用 URL (例如 exampleapp://oauth_redirect)

如果授权服务器策略允许, 公共客户端可以使用本协议向授权服务器注册. 公共客户端在 "token_endpoint_auth_method" 元数据字段中使用 "none" 值, 通常与 "implicit" 授权类型一起使用. 这些客户端通常是生命周期较短的浏览器内应用, 用于请求访问用户资源, 并且访问与用户在授权服务器上的活动会话绑定. 由于这类客户端通常没有长期存储, 它们可能需要在每次浏览器应用加载时重新注册. 为了避免由此产生大量失效客户端标识符, 授权服务器可以决定在一段时间后使满足特定条件的现有客户端注册过期. 或者, 这类客户端也可以在提供浏览器内应用代码的服务器上注册, 并且客户端配置可以随代码一起推送到浏览器.

由于不同 OAuth 2.0 授权类型具有不同的安全和使用属性, 授权服务器可以要求一份软件为支持多个授权类型进行分别注册. 例如, 授权服务器可能要求所有使用 "authorization_code" 授权类型的客户端都为 "token_endpoint_auth_method" 使用客户端密钥, 但任何使用 "implicit" 授权类型的客户端都不在令牌端点使用任何认证. 在这种情况下, 服务器可以禁止客户端同时注册 "authorization_code""implicit" 授权类型. 类似地, "authorization_code" 授权类型用于表示代表最终用户的访问, 而 "client_credentials" 授权类型表示代表客户端自身的访问. 出于安全原因, 授权服务器可以要求这些不同用例使用不同作用域, 因而可以禁止同一个客户端同时注册这两种授权类型. 在所有这些情况下, 授权服务器都会以 "invalid_client_metadata" 错误响应作答.

除非客户端元数据作为软件声明 (software statement) 中的声明使用, 否则授权服务器必须把所有客户端元数据都视为自声明. 例如, 恶意客户端可能使用它试图模拟的合法客户端的名称和标志. 此外, 恶意客户端可能尝试使用合法客户端的软件标识符或软件版本, 以便在授权服务器上把自身与合法客户端实例关联起来. 为了应对这一点, 授权服务器必须查看整个注册请求和客户端配置, 并采取适当措施缓解此风险. 例如, 如果标志的域名/站点与重定向 URI 的域名/站点不匹配, 授权服务器可以发出警告. 对于请求不同重定向 URI 或不同客户端 URI 的已知软件标识符, 授权服务器也可以拒绝其注册请求. 在所有情况下, 授权服务器还可以向最终用户显示关于动态注册客户端的警告消息, 尤其是在这类客户端最近才注册, 或之前尚未被授权服务器上的任何用户信任时.

当授权服务器支持开放客户端注册时, 它必须极其谨慎地处理客户端提供且将显示给用户的任何 URL (例如 "logo_uri", "tos_uri", "client_uri""policy_uri"). 例如, 恶意客户端可以在注册请求中指定一个 "policy_uri", 指向诱导式下载, 诱使用户在授权期间点击它. 授权服务器应当检查 "logo_uri", "tos_uri", "client_uri""policy_uri" 是否与 "redirect_uris" 数组中定义的 URI 具有相同 host 和 scheme, 并且所有这些 URI 都能解析到有效网页. 由于这些 URI 值意在授权页面显示给用户, 授权服务器应当在可能的情况下保护用户免受这些 URL 上托管的恶意内容影响. 例如, 在授权页面向用户呈现这些 URL 之前, 授权服务器可以下载这些 URL 上托管的内容, 用恶意软件扫描器和黑名单过滤器检查内容, 判断该 URL 是否混合了安全和非安全内容, 并应用其他可能的服务器端缓解措施. 注意, 这些 URL 中的内容可能随时变化, 授权服务器无法对 URL 的安全性提供完全信心, 但这些做法会有所帮助. 为了进一步缓解这类威胁, 授权服务器还可以警告用户: 这些 URL 链接由第三方提供, 应谨慎对待, 且并非由授权服务器自身托管. 例如, 授权服务器可以不直接在 HTML 锚点中提供链接, 而是在允许用户继续访问目标 URL 前, 先把用户引导到一个中间警告页面.

客户端可以在注册请求中同时使用直接 JSON 对象和 JWT 编码的软件声明, 向授权服务器呈现客户端元数据. 软件声明受密码学保护, 表示声明签发者作出的声明; JSON 对象则表示客户端或开发者直接作出的自声明. 如果软件声明有效, 并由可接受的权威方 (例如软件 API 发布者) 签名, 则软件声明中的客户端元数据值必须优先于普通 JSON 对象中呈现的那些元数据值, 因为后者可能已被截获并修改.

与所有元数据值一样, 软件声明也是客户端自声明的项目, 即使其内容已由软件声明签发者进行数字签名或 MAC 保护. 因此, 在多数情况下, 呈现软件声明不足以完全识别某个客户端软件. 相比之下, 初始访问令牌不一定包含关于特定客户端软件的信息, 而是表示使用注册端点的授权. 授权服务器在决定是否接受某个注册请求时, 必须考虑完整注册请求, 包括软件声明, 初始访问令牌以及 JSON 客户端元数据值.

如果授权服务器收到一个客户端注册请求, 而该客户端并不打算同时注册多个实例, 并且授权服务器可以推断出重复注册 (例如, 它使用与另一个现有客户端相同的 "software_id""software_version" 值), 则服务器应当把新注册视为可疑并拒绝注册. 新客户端可能正试图模拟现有客户端以诱骗用户授权它, 或原始注册可能已不再有效. 管理这种情况的细节取决于授权服务器部署, 不在本规范范围内.

由于客户端标识符是公共值, 可在授权端点用于模拟客户端, 因此决定向已注册客户端的多个实例签发相同客户端标识符的授权服务器, 必须非常明确允许这种情况发生的条件. 例如, 授权服务器可以把给定客户端标识符限制为仅用于使用相同基于重定向流程和相同重定向 URI 的客户端. 授权服务器不应向已注册客户端的多个实例签发相同客户端密钥, 即使它们被签发了相同客户端标识符也不应这样做, 否则客户端密钥可能泄漏, 使恶意冒名者能够模拟机密客户端.