在基于 Web 的单页应用程序 (SPA) 中使用带有授权码 + PKCE 的 OIDC/OAuth 2 进行用户身份验证时,可以生成随机数参数并将其发送到身份提供商以减轻重放攻击。
https://oa.dnc.global/-OpenID-Connect-Autorisation-via-un-code-Authorization-Code-Flow-.html
虽然现时参数对于现已废弃的隐式流程是必需的,但对于授权代码流程来说是可选的。
如果不使用nonce参数,潜在的攻击向量是什么?
如果 JWT 中的随机数声明不匹配,SPA 可以验证 ID 令牌无效,但是攻击者何时可以向 SPA 发送有效但被盗的 ID 令牌?
TLDR;
nonce
旨在提供针对授权代码注入攻击的保护,但对于公共客户端(例如 SPA),它不提供这种保护。
有关
nonce
参数提供什么保护的说明,请查看此处:
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#nonce_as_injection_protection
最后一段解决了您关于
nonce
专门为公共客户提供哪些保护的问题,例如SPA:
需要注意的是,nonce 并不保护公共客户端的授权码,因为攻击者不需要执行授权码注入攻击。相反,攻击者可以使用窃取的授权代码直接调用令牌端点。
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.5.3.2-4
下一节将解决下一个问题,即“如果
nonce
参数不能为公共客户端提供保护,那么我应该使用什么?”
PKCE 是 OAuth 客户端最明显的解决方案,因为它现在可用(最初用于 OAuth 本机应用程序),而 nonce 适用于 OpenID Connect 客户端。
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.5.3.3-2
现在,如果您问 PKCE 和
nonce
之间的区别是什么,以及为什么 PKCE 可以保护公共客户端,而 nonce
则不能,区别在于它们发挥作用的 OAuth/OIDC 流程的不同步骤。
随机数由客户端生成并与授权请求一起发送,类似于 PKCE 中的
code_challenge
和 code_challenge_method
(可选)。 OP 存储值并返回 authorization code
。然而,接下来的内容有所不同。
使用
nonce
:
authorization code
发送给 OP。nonce
放入(ID
)令牌中并返回令牌nonce
值与会话存储中的值进行检查使用 PKCE:
authorization code
AND code_verifier
发送到 OPcode_verifier
进行转换来检查 code_challenge_method
,并检查它是否与之前收到的 code_challenge
匹配。我将每个“发生保护”的步骤加粗。使用
nonce
客户端的负担更大,需要验证令牌中的 nonce
值与其之前创建和存储的值是否匹配。通过 PKCE,OP 可以完成 code_verifier
变换,并将其与之前的 code_challenge
进行比较。
如果恶意客户端能够窃取授权代码,则无法防止该客户端获取令牌并使用它。它不必检查
nonce
参数。它不在乎。但是,使用 PKCE,恶意客户端需要拥有 code_verifier
,否则 OP 将不会返回令牌。