ChatGPT解决这个技术问题 Extra ChatGPT

OAuth 2.0“状态”和OpenID“nonce”参数之间的区别?为什么状态不能被重用?

OAuth 2.0 定义了客户端在请求中发送的“状态”参数,以防止跨站点请求攻击。 OpenID 规范中也提到了“nonce”。除了在 ID 令牌而不是查询参数中返回“nonce”这一事实之外,它们似乎服务于完全相同的目的。如果有人能解释为什么他们是分开的

刚刚发现一篇非常好的文章,深入地回答了这个问题danielfett.de/2020/05/16/pkce-vs-nonce-equivalent-or-not

C
Community

状态和随机数似乎相似。但是如果你深入挖掘,你会发现它们有不同的用途。

State 用于保护最终用户免受跨站请求伪造 (CSRF) 攻击。它是从 OAuth 2.0 协议 RFC6749 引入的。议定书指出,

一旦从最终用户获得授权,授权服务器将最终用户的用户代理重定向回客户端,并使用“state”参数中包含的所需绑定值。绑定值使客户端能够通过将绑定值与用户代理的身份验证状态匹配来验证请求的有效性

这用于授权请求。它使客户端能够验证授权响应未被更改并由原始服务器发送。请求已发送。简而言之,它允许客户端交叉检查授权请求和响应。

(详细说明:要接受授权码响应,客户端需要接受来自授权服务器的响应(例如:- 在 Web 应用程序中,这可以通过重定向和表单发布到后端来完成)。这意味着,我们的客户端应用程序有一个开放并接受请求的端点。状态参数通过将原始授权请求绑定到响应来保护此端点。这是 CSRF 保护。)

Nonce 有不同的用途。它将令牌与客户端绑定。它用作令牌验证参数,从 OpenID Connect specification 引入。

nonce - 用于将客户端会话与 ID 令牌相关联并缓解重放攻击的字符串值。该值未经修改地从身份验证请求传递到 ID 令牌。如果 ID 令牌中存在,客户端必须验证 nonce Claim Value 是否等于在 Authentication Request 中发送的 nonce 参数的值。如果存在于认证请求中,授权服务器必须在 ID 令牌中包含一个 nonce 声明,声明值是在认证请求中发送的 nonce 值。授权服务器应该不对使用的 nonce 值执行其他处理。 nonce 值是区分大小写的字符串

如您所见,nonce 值源自授权请求,由客户端生成。如果包含 nonce,它将出现在令牌中。因此客户端可以根据初始授权请求验证它收到的令牌,从而确保令牌的有效性。

此外,根据流类型,nonce 可以是强制参数。隐式流和混合流要求 nonce 值。这两个值都由客户端应用程序生成和验证。

为什么状态不能被重用?

如果捕获到授权请求,则恶意方可以伪造授权响应。这可以通过更改状态参数来避免。


如果我们在 ID 令牌中将状态本身作为 nonce 并且也在它之外传递,那么会有什么缺点。使用外部来防止 CSRF,内部来在客户端绑定会话。
@dvsakgec 从协议的角度来看,重要的是利用状态和随机数进行安全和验证。据我所知,规范并不限制您对状态和随机数使用相同的值。在复杂的攻击向量中,人们可能能够从授权响应中提取状态值(例如:移动应用程序)。因此,具有相同的值会从您的令牌验证过程中删除一个条件,这并不好
抱歉迟到了,但是对于可以从响应中取出状态参数的论点,完全杀死了状态参数的目的。此外,如果两者都使用相同的参数,那么在 OpenID Connect 流的情况下,复杂的攻击将不起作用,因为从反向通道调用收集的 ID 令牌将具有相同的参数,并且客户端可以比较两个调用的状态参数以检查之前打的电话。
@KavinduDodanduwa 感谢您的精彩解释。 Nonce 似乎要安全得多,那么为什么我们需要放入一个 state 参数,如果它会被操纵,并且我们可以放入 nonce 参数呢?
@avisiboni 接受授权码响应,客户端需要接受来自授权服务器的响应(例如:- 在网页中,这可以通过重定向和表单发布到后端来完成)。这意味着,我们的客户端应用程序有一个开放并接受请求的端点。状态参数通过将原始授权请求绑定到响应来保护此端点。这是 CSRF 保护。 Nonce 是完全不同的,两者都用于不同的目的。
P
Pithikos

Nonce 回答了浏览器的问题:这个 ID 令牌是对我最初请求的响应吗?

说明对后端服务器的回答:同意真的来自我认为的人吗?

所以他们回答类似的问题,但针对不同的实体。


不是相反吗?据我了解,state 用于浏览器,而 nonce 用于服务器。
@RafaelEyng 你可能是对的。很长一段时间我都沉迷于此。可能一些参考会有所帮助。除了命名之外,它们的功能也如前所述。
M
Mayur Dighe

我从他们的 RFC 中说明了一个解释。解释很简单。

状态

客户端用来维护请求和回调之间状态的不透明值。授权服务器在将用户代理重定向回客户端时包含此值。该参数应该用于防止跨站请求伪造

随机数

nonce 参数值需要包含每个会话的状态并且攻击者无法猜测。为 Web 服务器客户端实现此目的的一种方法是将加密随机值存储为 HttpOnly 会话 cookie,并使用该值的加密哈希作为 nonce 参数。在这种情况下,返回的 ID 令牌中的随机数与会话 cookie 的哈希值进行比较,以检测第三方的 ID 令牌重放。适用于 JavaScript 客户端的相关方法是将加密随机值存储在 HTML5 本地存储中,并使用该值的加密哈希。

参考链接:状态:https://datatracker.ietf.org/doc/html/rfc6749

随机数:https://openid.net/specs/openid-connect-core-1_0-17_orig.html

希望这能回答你的问题。


只是-1,因为我认为 OP 更要求解释两者的使用方式的差异,而不是 RFC 的片段。
正如我在回答中提到的,来自 RFC 的片段是不言自明的。
“自我解释”是一个非常主观的东西。我已经阅读了规格,但仍然没有得到区别。不要假设一个人的理解水平与你从一个确切地问一个关于微妙之处的问题的人那里得到的理解水平相同。
去掉了这个词。
@MayurDighe 我愿意。但是,如果您添加链接,这个答案会很棒。 IMO,它将大大提高答案的质量。
N
Nicolas Dao

除了上述侧重于 statenonce 安全方面的答案之外,如果您正在实施自己的三足 OAuth2 工作流程(客户端、中间件和联合身份提供程序,例如 Facebook),您的中间件可能有时需要一些上下文。例如,当 FIP 的响应在返回到客户端之前返回到您的中间件时,您可能需要了解更多有关原始请求的详细信息(即,对 FIP 的原始请求)。因为您的中间件很可能是无状态的,所以如果没有任何帮助,它将无法回答这个问题。这就是 OAuth2 state 变量的用武之地。您可以存储任何表示您希望在所有 OAuth2 跳转之间传递的状态的字符串,以便您的中间件(以及您的客户端)可以使用更多上下文。对于您的客户,这是出于安全原因使用的。出于纯粹的安全原因,nonce 被用作 OIDC 规范的一部分。


H
Haifeng Won

作为 MiiT 参与者,Mallory 以某种方式截获 ID 令牌并将令牌中继到依赖方(也称为受保护服务、资源服务器)。依赖方拒绝 ID 令牌,因为 Mallory 的浏览器中没有 session cookie。 nonce 和 session 的简化关系,nonce = hash(session, seed_rotated_regularly)

状态是依赖方在每个 HTTP 响应中生成的 CSRF token。作为用户,Alice 不小心点击了钓鱼链接,她的用户代理被重定向到身份验证服务(又名 OP,IdP)。由于单点登录,Alice 不会注意到来回的 HTTP 302。假设在 redirect_uri 中允许钓鱼网站。依赖方可以使用钓鱼网站获得的有效令牌拒绝 HTTP 请求,因为没有显示状态。 Nonce 在这种情况下不起作用,因为会话 cookie 在 Alice 的用户代理中。 State 无法阻止 MiiT,因为 Mallory 可以获取令牌、状态,但不能获取会话 cookie。


l
ligarba

实际上“NONCE”足以验证发送者和响应。但在您打开令牌之前应该阅读“NONCE”。因此,如果有数百万个虚假响应,您必须接受响应,您将接受所有这些以打开令牌并阅读“NONCE”。但是状态已经在响应头上打开,您可以轻松读取状态并轻松拒绝虚假响应。这是两级检查。


q
qazwsx123

为了演示差异,让我们考虑一种情况,其中 state 存在但 nonce 不存在,并且攻击者能够拦截身份验证响应(从授权服务器或 OIDC 提供程序重定向到客户端)并注入恶意授权代码具有相同的 state 参数。这更可能发生在原生应用程序中,可以通过使用 nonce 参数方法来缓解。

或者攻击者可以很容易地使用在攻击者的客户端应用程序上截获的授权码来登录受害者的帐户。 (如果存在 nonce,也可能发生这种情况,因为攻击者可以更改客户端应用程序以绕过 nonce 检查。授权服务器或 OIDC 提供者应通过检测相同授权代码的多次使用或给予完全相同的同意来防止这种情况短时间内)

PKCE 也可以用作一种复杂的方法,但是所有的授权服务器或 OIDC 提供者可能不支持它。