Map

Stop using JWTs (samsch gist)

Wiki summaryauthenticationsecurityweb โ†ณ show in map Markdown
title
Stop using JWTs (samsch gist)
type
summary
summary
Long-circulating gist arguing JWTs are wrong for sessions; use cookie sessions, and use PASETO for the rare short-lived-token cases
tags
authentication, security, web
created
2026-04-25
updated
2026-04-25

A short, blunt gist by GitHub user samsch arguing that JWTs should not be used for keeping users logged in. They aren't designed for it, the spec family has a poor security track record, and there's a much better tool that already exists: regular cookie sessions. The gist is widely linked in web-auth threads as the short-form rebuttal to the JWT-for-sessions pattern. It cites longer pieces by joepie91 and Paragon Initiative as the deeper reading.

The core argument

Four reasons the gist gives for not using JWTs as session tokens:

  1. Lifetime mismatch. The JWT spec is designed for very short-lived tokens (~5 minutes or less). Sessions need longer lifespans. Stretching JWTs to fit means building revocation, rotation, and lifetime management โ€” features the spec deliberately doesn't provide.
  2. "Stateless" auth isn't real. You cannot securely have stateless authentication without massive resources (revocation lists, rotation, blocklists for compromised tokens). Once you accept you need a store, you might as well store everything and use a regular session ID. samsch links to a sister gist titled "Stateless is a lie."
  3. JWTs as session tokens are strictly worse than cookie sessions. A JWT containing only a session ID is bigger, slower, and less flexible than a session cookie. It buys nothing.
  4. The JWT spec is distrusted by security experts. The original spec made alg: none forgeries possible. The JOSE family has had repeated implementation footguns. samsch's takeaway: this should preclude all use of JWTs for security-related purposes. Links Paragon's deeper takedown.

Don't use localStorage for credentials

Tangentially: don't use localStorage or sessionStorage to hold authentication credentials, including JWTs. Cited reference is Randall Degges' 2018 piece on the topic. The reason cookie-based session storage isn't replaceable by JS-accessible storage is XSS exposure: any script that loads in your origin can read every entry in localStorage. HttpOnly cookies cannot be touched by JS at all.

Rebuttals

The gist ends with three pre-empted objections:

  • But Google uses JWTs! โ€” Google does not use JWTs for browser sessions. They use regular cookie sessions. Google's JWTs are SSO transports โ€” short-lived bearer tokens that move a login from one host to another. That's within the reasonable use cases for JWTs, and Google has the security resources to implement it carefully. Their JWT usage isn't yours.
  • But stateless is better! โ€” See the "Stateless is a lie" companion gist. You can't have truly stateless auth at any reasonable security level.
  • I don't know how to set up sessions! โ€” Sessions don't have many recent articles because the technology isn't new. Most web frameworks ship session middleware. For Express, use express-session with a store connector like connect-session-knex against Postgres/MySQL/SQLite.

When JWTs (or PASETO) are appropriate

The gist concedes that signed short-lived tokens have legitimate uses โ€” SSO transports, password-reset links, email-verification links, capability tokens that expire in minutes. For those, samsch points to paseto as the better-designed, less-footgun successor to the JOSE family. Stop using JWTs even there if you can; if you can't, prefer PASETO.

Why this gist gets cited so often

Because the JWT-as-session pattern is the default in countless tutorials and bootcamp curricula, and the case against it has to be repeated constantly. samsch's gist is the short, link-friendly version of the longer joepie91 + Paragon pieces, which is why it ends up pasted in pull-request reviews and Reddit threads year after year.