Stop Using JWTs

JWTs (JSON Web Tokens) are under fire for being overused and misapplied, especially as long-lived, browser-based session tokens where revocation, XSS exposure, and complex cryptographic footguns make them hard to use safely. Many commenters argue that traditional server-side sessions with opaque, random IDs stored in HttpOnly cookies are simpler, easier to invalidate, and adequate for most web apps, while JWTs still shine for short‑lived, service‑to‑service or federated authentication where stateless verification is valuable. Alternatives like PASETO, macaroons, or signed but opaque tokens are mentioned, but there is no universal replacement—only a strong theme that engineers should be more selective and conservative about when JWTs are actually the right tool.

Scope of the debate

  • Most participants distinguish two main use cases:
    • Browser-based user sessions.
    • Service‑to‑service / backend tokens.
  • Broad soft consensus: JWTs are often a poor fit for browser sessions, but can be fine or even ideal for backend and federation scenarios.

JWTs for browser-based sessions

  • Critics say JWTs add complexity over simple opaque session IDs in HttpOnly cookies, with no real benefit if the same server issues and validates them.
  • Main pain points raised:
    • Hard/awkward revocation and logout, especially per-device logout.
    • Replayability and long-lived tokens.
    • Tendency to stuff sensitive or mutable data into tokens, creating cache invalidation and security problems.
  • Several argue: if you already need a datastore (for users, permissions), just store session state there and avoid cryptography for sessions.

Security properties and implementation pitfalls

  • Historical issues: alg=none, algorithm downgrade/confusion, libraries accepting public keys as HMAC secrets, poor defaults.
  • Some argue these were library bugs and are mostly fixed; others say they stem from a spec that encourages footguns and complexity.
  • Disagreement on how “insecure” JWT is today:
    • One camp: “JWT is fine if you constrain algorithms and use good libs.”
    • Other camp: “Spec encourages misuse; CVEs keep appearing; safer designs exist.”

Revocation, “stateless” auth, and logout

  • Core tension: JWTs are marketed as “stateless,” but secure logout and compromise handling require state:
    • Revocation lists / denylists.
    • Per‑user “not valid before” timestamps.
    • Key rotation schemes.
  • Some argue once you add that state, you’ve lost the main advantage over classic sessions.
  • Others counter that revocation lists are much smaller than full session stores and easier to replicate globally.

Cookies, storage, and XSS/CSRF

  • Strong support for HttpOnly, Secure, SameSite cookies for browser sessions.
  • Many caution against storing JWTs in localStorage due to XSS exfiltration; some downplay this if you “don’t allow untrusted JS,” others call that unrealistic.
  • Point that HttpOnly prevents token theft but not XSS-driven misuse.

Alternatives and broader ecosystem

  • Alternatives mentioned: opaque random tokens, signed cookies, PASETO, macaroons, SAML/OIDC patterns, custom schemes.
  • Some praise PASETO/macaroon designs as more misuse-resistant but note limited ecosystem and adoption.
  • Several view the “stop using JWTs” framing as overblown or clickbait; prefer “use JWTs narrowly and carefully.”