OAuth授权请求中'state'参数的用途是什么

问题描述 投票:0回答:2

在 OAuth 中,初始授权请求有一个

state
参数。显然它是出于安全原因而存在的,但我真的不明白它保护什么......例如,在 GitHub 上这个参数的描述是:

不可猜测的随机字符串。它用于防止跨站点请求伪造攻击。

据我所知,授权请求的状态只是作为参数传递给重定向 URL,如下所示:

http://<redirect_url>?code=17b1a8df59ddd92c5c3b&state=a4e0761e-8c21-4e20-819d-5a4daeab4ea9

有人可以解释一下这个参数的确切用途吗?

security oauth
2个回答
58
投票

state参数用于防御XSRF。您的应用程序生成一个随机字符串并使用状态参数将其发送到授权服务器。授权服务器发回状态参数。如果两个状态相同=> OK。如果状态参数不同,则表明有其他人发起了请求。

Google 的示例可能更清楚:https://developers.google.com/accounts/docs/OAuth2Login?hl=en#createxsrftoken


0
投票

state 在发送到redirect_uri 的查询字符串中回显。它有两个目的:

  1. 顾名思义,最初的用途是将状态信息从发起网页传输到redirect_uri。例如,我有一个流程向用户发送一个链接,允许他们将其帐户链接到其他一些资源。该链接包含描述该资源的信息(令牌)。因此,用户单击该链接,他们将被带到一个网页,在那里他们被重定向到身份验证服务器。我需要该令牌通过身份验证过程返回到redirect_uri,以便redirect_uri 背后的业务逻辑可以完成将资源链接到用户帐户。我通过使用“状态”来携带该信息来做到这一点。鉴于“状态”没有大小限制,如果可以用来携带各种非常有用的信息。

  2. 作为防范 XSRF 的一种手段...第三方很容易伪造对身份验证服务器的请求并欺骗您的 redirect_uri 接受响应。如果状态信息是随机生成的值并且redirect_uri能够以某种方式验证它是它自己的,那么您可以保护自己免受这种情况的影响。

随机值必须绑定或存储在某个会话中是一种误解。尽管这是验证状态的有效方法,但它是有缺陷的。如果身份验证存在延迟(例如,用户在登录屏幕上挂起几个小时),那么如果会话已过期,这种验证方法就会失败。如果用户错误或双击发起多次登录,也会失败。

恕我直言,使用私钥对随机值进行签名要好得多。例如以随机数+私钥的SHA1或SHA256哈希作为签名。将状态值设为随机数和签名的组合。请注意,您会将二进制值转换为 Base64。通常使用句号作为分隔符,就像 JWT 一样:

状态=随机+“。” + 签名

其中签名= BASE64_SHA256(随机+私钥)

您可以通过在句号处分割状态值来验证这一点,如下所示:

verifyValue = BASE64_SHA256(split(state,".")[0] + privateKey)

如果 verifyValue = split(state,".")[1] 则状态有效。没有烦人的会话存储,因此验证速度要快得多。

将这两个目的合二为一是完全可行的。也就是说,您可以获取您希望redirect_url 了解的已知值,添加随机数,然后添加签名作为两个值的 SHA256 哈希值。例如:

状态=数据+“。” +随机+“。” + 签名

其中签名= BASE64_SHA256(数据+“.”+随机+私钥)

这是超级安全的,因为所有状态信息都经过完全签名和保护,如果您使用针对会话存储的简单安全令牌,则不会发生这种情况(按照 https://developers.google.com/identity 中的方法) /openid-connect/openid-connect?hl=en#createxsrftoken)

© www.soinside.com 2019 - 2024. All rights reserved.