跳到主要内容

7. 安全考虑事项 (Security Considerations)

7.1 code_verifier 的熵 (Entropy of the code_verifier)

安全模型依赖于这样一个事实: 攻击者无法获知或猜出代码验证器 (code verifier). 遵守这一原则至关重要. 因此, 代码验证器必须以加密随机方式生成, 并具有足够高的熵, 使攻击者在实践中无法猜测其值.

客户端应当创建一个至少具有 256 比特熵的 "code_verifier". 这可以通过让合适的随机数生成器创建一个 32 八位字节序列来完成. 随后可以对该八位字节序列进行 base64url 编码, 生成一个 43 八位字节的 URL 安全字符串, 作为具有所需熵的 "code_challenge" 使用.

7.2 防止窃听者 (Protection against Eavesdroppers)

客户端在尝试 "S256" 方法后禁止降级到 "plain". 支持 PKCE 的服务器必须支持 "S256", 不支持 PKCE 的服务器则会直接忽略未知的 "code_verifier". 因此, 当提供 "S256" 时出现错误, 只能表示服务器有缺陷, 或者中间人 (MITM) 攻击者正在尝试降级攻击.

"S256" 方法可以防止窃听者观察或截获 "code_challenge", 因为没有验证器时无法使用该挑战值. 使用 "plain" 方法时, 攻击者有机会在设备上或 HTTP 请求中观察到 "code_challenge". 由于在这种情况下代码挑战与代码验证器相同, "plain" 方法不能防止对初始请求的窃听.

使用 "S256" 可以防止 "code_verifier" 值泄露给攻击者.

因此, 不应使用 "plain"; 它仅为兼容已部署的实现而存在, 前提是请求路径已经受到保护. 新实现不应使用 "plain" 方法, 除非由于某种技术原因无法支持 "S256".

应当使用 "S256" 代码挑战方法或其他加密安全的代码挑战方法扩展. "plain" 代码挑战方法依赖操作系统和传输安全不向攻击者泄露请求.

如果代码挑战方法为 "plain", 并且为了实现无状态服务器而要在授权 "code" 中返回代码挑战, 则必须以只有服务器能够解密并提取它的方式进行加密.

7.3 对 code_challenge 加盐 (Salting the code_challenge)

为降低实现复杂度, 生成代码挑战时不使用盐值 (salt), 因为代码验证器已经包含足以防止暴力破解攻击的熵. 将一个公开已知的值连接到包含 256 比特熵的代码验证器后再用 SHA256 哈希以生成代码挑战, 并不会增加暴力破解有效代码验证器值所需的尝试次数.

虽然 "S256" 转换类似于对密码进行哈希, 但二者存在重要差异. 密码往往是熵相对较低的词, 可被离线哈希后在字典中查找. 在哈希前为每个密码连接一个唯一但公开的值, 可以大幅扩大攻击者需要搜索的字典空间.

现代图形处理器已经允许攻击者实时计算哈希, 速度快于从磁盘查找哈希. 即使对于低熵密码, 这也消除了盐值在增加暴力破解攻击复杂度方面的价值.

7.4 OAuth 安全考虑事项 (OAuth Security Considerations)

[RFC6819] 中给出的所有 OAuth 安全分析均适用, 因此读者应当仔细遵循其中建议.

7.5 TLS 安全考虑事项 (TLS Security Considerations)

当前安全考虑事项可见 "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)" [BCP195]. 该文档取代了 OAuth 2.0 [RFC6749] 中关于 TLS 版本的建议.