停止使用 JWT
Stop Using JWTs

原始链接: https://gist.github.com/samsch/0d1f3d3b4745d778f78b230cf6061452

JWT 不适合用于管理用户会话,不应将其用于此目的。与传统的基于 Cookie 的会话不同,JWT 缺乏长期身份验证所需的必要安全性和灵活性。 主要顾虑包括: * **设计缺陷:** JWT 规范旨在用于短效令牌(五分钟以内),而非长期会话。安全专家警告称,该规范包含固有的漏洞,例如存在伪造令牌的风险。 * **“无状态”的神话:** 真正的无状态身份验证是不安全的。妥善的会话管理需要服务器端数据存储,这使得标准会话 Cookie 更高效、更安全且更易于实现。 * **存储风险:** 由于跨站脚本攻击(XSS)的风险,凭据(包括 JWT)绝不应存储在 `localStorage` 或 `sessionStorage` 中。 * **正确使用场景:** 虽然谷歌等公司使用 JWT,但它们仅保留用于单点登录(SSO)传输等特定任务,而非浏览器会话。 如果您在其他任务中需要安全令牌,专家建议使用 **PASETO** 代替 JWT。对于用户身份验证,请依赖您的 Web 框架内置的成熟中间件所提供的标准会话 Cookie,这是一种经过验证且安全的管理用户状态的方法。

最近一篇在 Hacker News 上提倡“停止使用 JWT”的文章在社区中引发了广泛质疑。批评者认为,反对 JWT 的论点大多站不住脚,往往将糟糕的实现方式与标准本身的缺陷混为一谈。 评论者提出的主要反驳观点包括: * **语境至关重要:** JWT 在服务间通信中依然非常高效。 * **安全误区:** 许多关于 JWT “不安全”的说法(例如无法注销令牌或易受 XSS 攻击)都可以通过现代最佳实践来缓解,如使用短效令牌、刷新令牌轮换或采用安全的存储模式。 * **根本原因与工具的区别:** 评论者指出,近期诸如国际足联(FIFA)被黑客攻击等高调安全事件,其根源在于授权逻辑缺陷和客户端配置错误,而非使用 JWT 本身。 总的来说,共识在于只要实施得当,JWT 依然是一个稳健的工具。这场争论凸显了一个反复出现的主题:因开发者的错误或系统架构不当而导致的漏洞,不应归咎于标准本身。
相关文章

原文

TLDR: JWTs should not be used for keeping your user logged in. They are not designed for this purpose, they are not secure, and there is a much better tool which is designed for it: regular cookie sessions.

If you've got a bit of time to watch a presentation on it, I highly recommend this talk: https://www.youtube.com/watch?v=pYeekwv3vC4 (Note that other topics are largely skimmed over, such as CSRF protection. You should learn about other topics from other sources. Also note that "valid" usecases for JWTs at the end of the video can also be easily handled by other, better, and more secure tools. Specifically, PASETO.)

A related topic: Don't use localStorage (or sessionStorage) for authentication credentials, including JWT tokens: https://www.rdegges.com/2018/please-stop-using-local-storage/

The reason to avoid JWTs comes down to a couple different points:

  • The JWT specification is specifically designed only for very short-live tokens (~5 minute or less). Sessions need to have longer lifespans than that.
  • "stateless" authentication simply is not feasible in a secure way. You must have some state to handle tokens securely, and if you must have a data store, it's better to just store all the data. Most of this article and the followup it links to describes the specific issues: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
    • (Yes, people are doing it, and yes, their applications are flawed, and you should not repeat that mistake.)
  • JWTs which just store a simple session token are inefficient and less flexible than a regular session cookie, and don't gain you any advantage.
  • The JWT specification itself is not trusted by security experts. This should preclude all usage of them for anything related to security and authentication. The original spec specifically made it possible to create fake tokens, and is likely to contain other mistakes. This article delves deeper into the problems with the JWT (family) specification.

But Google uses JWTs! Google does not use JWTs for user sessions in the browser. They use regular cookie sessions. JWTs are used purely as Single Sign On transports so that your login session on one server or host can be transferred to a session on another server or host. This is within the reasonable usecases for JWTs, and Google has the resources (security experts) to create and maintain a more secure JWT implementation. Their JWTs are effectively not the same as anyone else's.

But stateless is better! You can't securely have truly stateless authentication without having massive resources, see the cryto.net link above. Also, Stateless is a lie.

I don't know how to setup sessions! You don't regularly see articles explaining sessions because the technology isn't particularly new. You also shouldn't need third party information for setup. A session implementation's documentation should take you through the setup process by itself. Almost any web server framework will contain an implementation for sessions, and usually it's very easy to enable if it isn't enabled by default. Express and other Node.js frameworks are somewhat exceptions to this rule, primarily because they are highly modular and single purpose. For Express, you simply use the express-session middleware and a store connector which works with your store (I recommend connect-session-knex, to be used with Postgres, MySQL, or possibly SQLite).

If you do need a short-lived, signed token for something, there is a better spec called PASETO which is designed to be secure. Just make sure you aren't using them for sessions.

I recommend checking out this gist by joepie91 to learn more how sessions work.

联系我们 contact @ memedata.com