Skip to content

Instantly share code, notes, and snippets.

@samsch
Last active July 17, 2026 16:25
Show Gist options
  • Select an option

  • Save samsch/0d1f3d3b4745d778f78b230cf6061452 to your computer and use it in GitHub Desktop.

Select an option

Save samsch/0d1f3d3b4745d778f78b230cf6061452 to your computer and use it in GitHub Desktop.
Stop using JWTs

Stop using JWTs!

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.

Rebuttals

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).

Short term tokens

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.

How sessions work

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

@julian-di

Copy link
Copy Markdown

what i like about jwt auth (for example when using keycloak), your frontend is responsible for providing a token, and your backend only for validating, this is in my mind a strong role seperation, and makes it easiert to extend. otherwise your app must implement bff flows (which can be a substential amount of code - which can go wrong) .

@Karl-Styner

Karl-Styner commented Jun 17, 2026

Copy link
Copy Markdown

Since I have already started writing about this, I would like to highlight at least one definite advantage of JWT.

Someone mentioned above about 'API keys.' These API keys are typically used to verify whether a user has the authority to access a specific API.

While API keys can be written in various formats, JWT is widely used because of the advantage that 'database connections are unnecessary for verification.'

Unless you have a completely single server, you are usually expected to have at least one additional server for verification; this authentication server handles the issuance, renewal, and revocation condition management of JWTs, as well as acting as an intermediary gateway for APIs.

Also, regarding the question of whether requests to the five mindplay-dk services mentioned above include a JWT, the answer is "Of course."

However, generally, as mentioned earlier, verification is not handled by the entire service but is performed at the mid-side gateway. Only verified requests are sent to the target service.

Searching through member tables or session tables for every request is overwhelmingly disadvantageous, considering that databases are typically more expensive resources than computing servers.

This cost-saving effect is sufficiently attractive, even taking into account some risk, and depending on the design of the revocation policy, it can prevent most risks.

What is truly dangerous is not the use of JWT itself, but

  1. Including sensitive information that should not be in the JWT

  2. Setting the JWT's validity period to an excessively long duration

  3. The absence of a disposal strategy

is likely.

For this reason, I feel a strong aversion to continuing the grandiose process known as 'sessions' simply because it is traditional.

Whether Stateless is false or the truth of the universe, I believe that [operating services efficiently based on a minimum level of safety] is a desirable direction to pursue as a member of a group.

@mrx23dot

Copy link
Copy Markdown

Whatever the new method is, it MUST be bound to the end user's device, thus cookie stealing is not a problem.

@sohanmaheshwar

Copy link
Copy Markdown

Couldn't agree more with this take!

In fact, I gave a lightning talk at Voxxed Days Amsterdam recently on why JWTs should not be used for Authorization and the YouTube comments were less than nice haha.

@onoffre65

Copy link
Copy Markdown

We're determined to reinvent the wheel. All of this already exists in the Jakarta EE standard. It has a predictable roadmap, independent of corporate whims.

@huggsboson

Copy link
Copy Markdown

We landed on JWT's just to unify the token format. We store an encrypted JWT with a session id and some items like scopes, user_id in the browsers cookie store. For service to service calls from a user's context we also pass forward session id, user id, scopes etc. It allows us to do user-based authorization at various points, but how to do that systematically and effectively is longer than a comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment