OAuth 2.0“状态”和OpenID“nonce”参数之间的区别?为啥状态不能被重用?
Posted
技术标签:
【中文标题】OAuth 2.0“状态”和OpenID“nonce”参数之间的区别?为啥状态不能被重用?【英文标题】:Difference between OAuth 2.0 "state" and OpenID "nonce" parameter? Why state could not be reused?OAuth 2.0“状态”和OpenID“nonce”参数之间的区别?为什么状态不能被重用? 【发布时间】:2018-04-01 08:11:01 【问题描述】:OAuth 2.0 定义了客户端在请求中发送的“state”参数,以防止跨站点请求攻击。 OpenID 规范中也提到了“nonce”。除了在 ID 令牌而不是查询参数中返回“nonce”这一事实之外,它们似乎服务于完全相同的目的。如果有人能解释为什么他们是分开的
【问题讨论】:
刚刚找到一篇非常好的文章,深入解答了danielfett.de/2020/05/16/pkce-vs-nonce-equivalent-or-not的问题 【参考方案1】:State 和 nonce 似乎很相似。但是如果你深入挖掘,你会发现它们有不同的用途。
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 是完全不同的,两者都有不同的用途。【参考方案2】:Nonce 回答浏览器的问题:这个 ID 令牌是对我的初始请求的响应吗?
向后端服务器说明答案:同意真的来自我认为的人吗?
所以他们回答类似的问题,但针对不同的实体。
【讨论】:
不是相反吗?据我了解,state
用于浏览器,nonce
用于服务器。
@RafaelEyng 你可能是对的。很长一段时间我都沉迷于此。可能一些参考会有所帮助。除了命名之外,它们的功能也如前所述。【参考方案3】:
我正在从他们的 RFC 中进行解释。解释很简单。
状态
客户端用来维护请求和回调之间状态的不透明值。授权服务器在将用户代理重定向回客户端时包含此值。该参数应该用于防止 跨站请求伪造
随机数
nonce 参数值需要包含每个会话的状态并且攻击者无法猜测。为 Web 服务器客户端实现此目的的一种方法是将加密随机值存储为 HttpOnly 会话 cookie,并使用该值的加密散列作为 nonce 参数。在这种情况下,返回的 ID 令牌中的随机数与会话 cookie 的哈希值进行比较,以检测第三方的 ID 令牌重放。适用于 javascript 客户端的相关方法是将加密随机值存储在 html5 本地存储中,并使用该值的加密哈希。
参考链接:状态:https://datatracker.ietf.org/doc/html/rfc6749
Nonce:https://openid.net/specs/openid-connect-core-1_0-17_orig.html
希望这能回答你的问题。
【讨论】:
只是一个-1,因为我认为 OP 更要求解释两者的使用方式的差异,而不是 RFC 的 sn-p。 正如我在回答中提到的,来自 RFC 的 sn-p 是不言自明的。 “不言自明”是一个非常主观的东西。我已经阅读了规格,但仍然没有得到区别。不要假设一个确切地问一个微妙问题的人的理解水平与你的理解水平相同。 删除了这个词。 @MayurDighe 我愿意。但是,如果您添加链接,这个答案会很棒。这将大大提高答案的质量,IMO。【参考方案4】:除了上述关注state
和nonce
安全方面的答案之外,如果您正在实施自己的三足 OAuth2 工作流程(客户端、中间件和联合身份提供商,例如 Facebook),您的中间件有时可能需要一些上下文。例如,当 FIP 的响应在返回到客户端之前返回到您的中间件时,您可能需要了解更多有关原始请求的详细信息(即,对 FIP 的原始请求)。因为您的中间件很可能是无状态的,所以如果没有任何帮助,它将无法回答这个问题。这就是 OAuth2 state
变量的用武之地。您可以存储任何表示您希望在所有 OAuth2 跳转之间传递的状态的字符串,以便您的中间件(以及您的客户端)可以使用更多上下文。对于您的客户,这是出于安全原因使用的。出于纯粹的安全原因,nonce
被用作 OIDC 规范的一部分。
【讨论】:
以上是关于OAuth 2.0“状态”和OpenID“nonce”参数之间的区别?为啥状态不能被重用?的主要内容,如果未能解决你的问题,请参考以下文章
OAuth 2.0 和 OpenID Connect 中的 JWT 安全性
OAuth 2.0 与 OpenID Connect 协议的完整指南