JWT 是不是共享/存储用于在客户端和服务器上签名的密钥?

Posted

技术标签:

【中文标题】JWT 是不是共享/存储用于在客户端和服务器上签名的密钥?【英文标题】:Does JWT share/store the secret for signing on both the client and server?JWT 是否共享/存储用于在客户端和服务器上签名的密钥? 【发布时间】:2016-03-07 15:29:23 【问题描述】:

我正在解决一些与 JWT 身份验证安全性相关的架构问题,并试图弄清楚以下几点:

    JWT 如何在服务器和客户端之间安全地传递密钥?

    看看下面的摘自https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/ ....................................

可以通过使用同步令牌模式来防止 CSRF。这听起来很复杂,但所有现代 Web 框架都支持这一点。

例如,AngularJS 有一个解决方案来验证 cookie 是否只能由您的域访问。直接来自 AngularJS 文档:

'在执行 XHR 请求时,$http 服务从 cookie 中读取一个令牌(默认为 XSRF-TOKEN)并将其设置为 HTTP 标头(X-XSRF-TOKEN)。由于只有在您的域上运行的 javascript 才能读取 cookie,因此您的服务器可以确信 XHR 来自在您的域上运行的 JavaScript。 您可以通过包含 xsrfToken JWT 声明使此 CSRF 保护无状态:'

"iss": "http://galaxies.com", "exp": 1300819380, "scopes": ["explorer", "solar-harvester", "seller"], "sub": "tom@andromeda.com", "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e"

    客户端如何创建和发送包含 xsrfToken 声明的有效请求,除非它可以在包含声明后首先签署 JWT? (毕竟这个 xsrfToken 应该是为了防止 EvilBob 伪造请求吧?)

关于我目前对 JWT XSRF 流程的理解的更多详细信息可以在这里找到http://spring.io/blog/2013/08/21/spring-security-3-2-0-rc1-highlights-csrf-protection/。

【问题讨论】:

【参考方案1】:

文章似乎将此称为“同步令牌模式”,但所描述的解决方案更适合Double Submit Cookies 方法而不是Synchronizer Token Pattern。

双重提交 cookie 涉及在标题或正文中发送 cookie 值,以及将其与自动发送的浏览器 cookie 一起发送。如果您不支持 CORS,那么在标头中设置令牌无论如何都是安全的,与任何自定义标头值一样(例如 X-Requested-With)。这是因为自定义标头首先无法跨域发送,因此验证它是否已从客户端传输来验证它不是来自另一个域。作为纵深防御策略,您可以将其设置为随机值,如this answer 所述。

随机值不需要来自服务器,也不需要签名。它只需要由 CSPRNG 生成。如果在客户端生成,则应使用window.crypto。服务器所做的只是检查标头和 cookie 值是否匹配。

第三方域无法伪造请求,因为即使浏览器会自动从受害者的机器发送 cookie 值,攻击者也不能在请求头或请求正文中包含该值。

使用同步器令牌模式,CSRF 令牌在服务器端生成并针对会话存储。该值必须从每个表单提交中发送,并在服务器端验证它是否与存储的令牌匹配。

【讨论】:

哇,非常感谢@SilverlightFox。这是非常彻底且非常有帮助的,包括多种选择。非常感谢您的反馈。【参考方案2】:

    我可以解释 Stormpath 是如何做到的,还有其他一些方法。 Stormpath 在 JWT 标头中包含一个“kid”(密钥 ID)字段,它是 API 密钥 ID/秘密对的标识符。 JWT 使用 Secret 进行签名,ID 存储在 key id 字段中。当 Stormpath 验证令牌时,它可以检索秘密。这适用于服务器和服务,但从不传递给客户端。使用客户端将单独的服务与秘密粘合在一起是非常不安全的。

    客户端不应该生成 JWT,这需要在服务器上完成。服务器知道 XSRF 令牌,可以在 JWT 中对其进行签名并将其放入 cookie 中。

希望这些信息对您有所帮助!

【讨论】:

好的,我对 JWT 流程的工作方式有一些误解。 1)服务器是唯一知道秘密的人。相同的 Secret 用于对所有用户的请求进行签名和验证。 2) 只有真正的客户端才能访问存储 auth-token 和 xsrf-token 的 cookie。攻击者可以提交攻击请求,但攻击请求不会将 xsrf-token 作为 HTTP 标头。从而使请求无效。 3) 请求到达服务器后,服务器会检查 header 是否包含 xsrf-token,如果是,则将其与 JWT payload 中的 xsrf-token 进行比较。 我第二次达沃林的困惑here ...所以我认为 1. xsrftoken 是在创建和签名 jwt 的同时创建的。 2. 它以非 httponly cookie 的形式出现在下游。 3. JWT 在 httpONLY cookie 中以减少 XSS。 4. ajax请求包含xsrfToken(只有同源JS知道),浏览器包含jwt(没有JS知道),服务器比较验证请求。这是计划吗?.... 一切都很好,但是... XSS 不能像从 localstorage 中获得 JWT 一样容易地获得 xsrftoken cookie,如果我使用它的话?

以上是关于JWT 是不是共享/存储用于在客户端和服务器上签名的密钥?的主要内容,如果未能解决你的问题,请参考以下文章

JSON WEB TOKEN(JWT)的分析

为啥 JWT Token 包含用于加密/签名的算法

各种微服务中 JWT 的共享签名密钥

与对称密钥相比,用对称密钥签名JWT会更有用吗?

JWT登录验证

在移动应用程序中签署 jwt 是不是安全?