HN Debrief

Stop Using JWTs

  • Security
  • Infrastructure
  • Developer Tools
  • Programming

The post is a blunt warning against using JWTs for web auth, especially the common pattern of storing a long-lived bearer token in browser storage and treating it like a session. The core complaint is not that signatures are fake security. It is that browser sessions need properties JWTs do not naturally give you: easy logout, easy per-session revocation, and a smaller blast radius when a token leaks. A signed token that can be replayed until expiry is a poor substitute for an opaque session ID the server can kill instantly.

If you run a normal web app, default to an opaque session cookie and server-side session storage. Keep JWTs for cases where one system issues claims and another verifies them without a shared session store, and be explicit about revocation, token lifetime, and where the token is stored.

Discussion mood

Mostly skeptical of the post’s absolutist title but aligned with its narrower point. People pushed back on “JWTs are bad” as clickbait, while still agreeing that JWTs are a poor default for browser sessions because revocation, replay, and storage choices erase the supposed stateless win.

Key insights

  1. 01

    HttpOnly changes the XSS blast radius

    HttpOnly cookies do not make XSS harmless, but they do stop an injected script from extracting the credential and replaying it from another machine. That is a meaningful security boundary. A token in localStorage can be copied out and abused for its full lifetime, which turns a same-origin bug into an off-site credential theft problem.

    If a browser must carry a session credential, prefer an HttpOnly cookie over JavaScript-readable storage. You still need XSS defenses, but you avoid handing attackers a reusable bearer token.

      Attribution:
    • eranation #1
  2. 02

    JWT complexity created real validation bugs

    The case against JWT is not theoretical hand-wringing. People pointed to a long history of broken library behavior around algorithm handling and key confusion, plus an Auth0 validation bypass, to show that the format’s flexibility repeatedly opened dangerous paths in real systems. The issue is not that signatures are weak. It is that JOSE gives implementers enough knobs to make bad states possible.

    Treat JWT support as a high-risk dependency surface, not a solved primitive. If you keep using it, pin accepted algorithms, validate issuer and audience strictly, and avoid libraries or wrappers that try to be too generic.

      Attribution:
    • RagingCactus #1
    • tptacek #1
    • agwa #1
  3. 03

    Revocation restores state and kills the pitch

    Per-token revocation lists and per-user invalidation timestamps both reintroduce server state. They also expose a sharp product tradeoff. A per-user cutoff is easy, but it logs out every device. Per-token revocation preserves device granularity, but now you are maintaining token state anyway. That leaves little of the original “stateless sessions” story standing.

    Decide first whether you need logout per device, global signout, or compromise response. If you do, model that state directly and do not pretend a browser session is stateless.

      Attribution:
    • chuckadams #1
    • dchest #1
    • Sohcahtoa82 #1
  4. 04

    Global distribution is the strongest pro-JWT argument

    The most credible defense of JWTs came from multi-region systems. A compact revocation list or per-user invalidation data can be replicated cheaply to edge locations, while a central session store adds latency you cannot beat with clever engineering. For globally distributed services, signed tokens can reduce cross-region auth chatter in a way classic sessions do not.

    If your auth path crosses regions on every request, benchmark replicated session state against local token verification instead of following blanket advice. Geography and latency can justify more auth complexity.

      Attribution:
    • mewpmewp2 #1 #2
    • littlecranky67 #1
    • conradludgate #1
  5. 05

    Hybrid auth keeps sessions and scoped tokens separate

    Several practitioners described a pattern that avoids the worst tradeoffs on both sides. The browser keeps a normal session cookie and uses it to mint short-lived JWTs only when a downstream system needs portable claims, such as tenant-scoped API access or RabbitMQ permissions. That limits JWT exposure while preserving their utility for delegated authorization.

    Use JWTs as secondary artifacts, not your primary browser session. Keep the long-lived login in a cookie, then mint narrow, short-lived tokens for specific backends or brokers.

      Attribution:
    • 0x696C6961 #1
    • Grollicus #1
  6. 06

    Write the smallest JWT implementation you need

    One pragmatic security take was that most JWT libraries expose far more surface area than many applications need. If you have a narrow use case with one algorithm and a fixed claim set, a tiny purpose-built verifier can be easier to audit than a general JOSE framework full of optional features. That framing flips the usual “never roll your own” instinct on its head for this particular format.

    If you truly need JWTs in a constrained environment, reduce the implementation to one algorithm and a minimal claim schema. Avoid “supports everything” auth stacks when your use case does not need them.

      Attribution:
    • andreyvit #1

Against the grain

  1. 01

    Short-lived JWTs can be good enough

    A smaller camp argued that browser use is acceptable if tokens are signed correctly, scoped with audience claims, and kept very short lived with refresh handled by a separate authority. From that angle, a 5 to 15 minute replay window is an operationally reasonable risk, especially when auth is intentionally separated from application services.

    If you choose browser JWTs anyway, write down the replay window you are accepting and justify it. Keep expiries short, isolate issuance, and do not let “stateless” become an excuse to skip refresh and revocation design.

      Attribution:
    • tracker1 #1 #2
    • hparadiz #1
  2. 02

    Cookie orthodoxy understates cookie tradeoffs

    Some pushback focused on how quickly people treat cookies as the obviously safer answer. Cookies still ride along on same-origin requests under XSS. They still have their own configuration foot-guns. And at larger scale, signed client-side state can be operationally simpler than checking a shared session store on every request. That does not rescue localStorage as a default, but it does puncture the idea that cookies are a free security upgrade.

    Do not replace one auth mechanism with another by slogan. Review your actual attack model, browser behavior, and infra topology before declaring cookies categorically safer or simpler.

      Attribution:
    • adithyassekhar #1
    • szmarczak #1
    • stickfigure #1
  3. 03

    PASETO is not a clean escape hatch

    Even commenters sympathetic to the anti-JWT argument were unconvinced that PASETO is the answer. The ecosystem is thinner, operational polish is weaker, and many of the historical JWT objections were aimed at old library defaults rather than unavoidable current practice. Swapping formats does not remove the need to reason about browser storage, revocation, and delegation.

    Do not treat format replacement as the whole auth strategy. If you are considering PASETO, evaluate library maturity and operational support first, then compare it against simply using sessions where possible.

      Attribution:
    • rdegges #1
    • feelingsonice #1
    • ForHackernews #1

In plain english

CSRF
Cross-site request forgery, an attack that tricks a browser into making an authenticated request the user did not intend.
HttpOnly
A cookie flag that prevents JavaScript in the page from reading the cookie value.
JOSE
JavaScript Object Signing and Encryption, the family of standards around JWT, JWS, JWE, and related token formats.
JWT
JSON Web Token, a compact signed or encrypted token format that carries claims such as a user ID or permissions.
PASETO
Platform-Agnostic Security Tokens, an alternative token format designed to avoid some JWT design pitfalls.
XSS
Cross-site scripting, a bug that lets attacker-controlled JavaScript run in a victim’s browser on a trusted site.

Reference links

JWT critiques and guidance

JWT vulnerability examples

Revocation and token design alternatives

  • A new approach to JWT revocation
    Proposed per-user secret rotation scheme that commenters argued was not really stateless
  • PASETO
    Alternative token format proposed by some commenters as safer than JWT, though others questioned its ecosystem maturity

Related concepts and data structures

  • Thundering herd problem
    Referenced in the context of mass token invalidation causing many clients to re-authenticate at once
  • OpenClaiming
    Commenter-proposed alternative protocol for signed claims and web authentication
  • OpenClaiming GitHub
    Source repository for the alternative protocol mentioned in the comments