Hacker News June 17, 2026 20 min signal 2026-06-17

Stop using JWTs

Archived text mirror, captured for personal reading when the Signal ran. Formatting is approximate — read the original at the source.

Stop using JWTs · GitHub

Skip to content

[](https://gist.github.com/)

Search Gists Search Gists

All gistsBack to GitHubSign inSign up

[](https://gist.github.com/)

Sign inSign up

You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert

{{ message }}

Instantly share code, notes, and snippets.

![Image 1: @samsch](https://gist.github.com/samsch)

samsch/**stop-using-jwts.md**

Last active June 17, 2026 13:54

Show Gist options

* Embed # Select an option

  • Embed Embed this gist in your website.
  • Share Copy sharable link for this gist.
  • Clone via HTTPS Clone using the web URL.

No results found

Learn more about clone URLs

Clone this repository at <script src="https://gist.github.com/samsch/0d1f3d3b4745d778f78b230cf6061452.js"></script>

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

CodeRevisions 9Stars 374Forks 20

Embed

Select an option

  • Embed Embed this gist in your website.
  • Share Copy sharable link for this gist.
  • Clone via HTTPS Clone using the web URL.

No results found

Learn more about clone URLs

Clone this repository at <script src="https://gist.github.com/samsch/0d1f3d3b4745d778f78b230cf6061452.js"></script>

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

Download ZIP

Stop using JWTs

Raw

**stop-using-jwts.md**

Stop using JWTs!

[](https://gist.github.com/samsch/0d1f3d3b4745d778f78b230cf6061452#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

[](https://gist.github.com/samsch/0d1f3d3b4745d778f78b230cf6061452#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

[](https://gist.github.com/samsch/0d1f3d3b4745d778f78b230cf6061452#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

[](https://gist.github.com/samsch/0d1f3d3b4745d778f78b230cf6061452#how-sessions-work)

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

[](https://gist.github.com/samsch/0d1f3d3b4745d778f78b230cf6061452)

![Image 2: @samsch](https://gist.github.com/samsch)

**samsch** commented Apr 13, 2019

Copy link Copy Markdown

Author

_"Sessions don't make any sense in a stateless API."_

Users, and any other data in your application, are state.

If you have users, you have a stateful service. If you have a stateful service, you most likely have a DB of some kind. If you have a DB of some kind, you can use sessions (while keeping your API services "stateless").

Sessions can be shared between servers that the client accesses (since the sessions are in the shared DB). Where those services are on different hosts, you use one-time tokens to identify that a new connection should be attached to a current session. Alternatively, separate services can use separate session mechanisms, and that's where a tool _similar_ to JWTs (trusted (signed), encrypted, one-time-use tokens containing user ID or other identification) can be used to do an autht transfer.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 3: @samsch](https://gist.github.com/samsch)

**samsch** commented Jul 5, 2019

edited

Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link Copy Markdown

Author

"Why does everyone recommend JWTs then?" or "Why are JWTs so popular?"

You probably didn't catch the YouTube link above, which explains how it got started near the end. The short version is that a certain subset of engineers got excited and started writing posts about JWTs when the spec was written. These articles were misunderstood, and the idea to use JWTs for sessions propagated largely through more blog posts. Primarily these articles were written by users who simply didn't understand the technology, but because the existing tools for sessions weren't "exciting" or new enough to be written about, the topic effectively flooded the Google results for how to do authentication with new and hip technologies (Angular, Node, React, etc).

After building up like this for a few years, the coding bootcamps started including JWTs in their lessons, furthering the myth that they are good for authentication by acting as an authority who should know. This happens because sadly bootcamps teach things that are popular, not real best practices and the best tools.

Cookies are an "old" tech. But being old doesn't make something better or worse, and often when it comes to security, something being older and unbroken is _much_ better than something newer and less proven.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 4: @vcarl](https://gist.github.com/vcarl)

**vcarl** commented Sep 29, 2020

Copy link Copy Markdown

I think this followup to a linked blog post is also a good resource (a flow chart of basically all the responses I've seen) http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-for-sessions-part-2-why-your-solution-doesnt-work/

And I like this slide of good uses for JWTs from this deck as well, (PDF) https://owasp.org/www-chapter-vancouver/assets/presentations/2020-01_Attacking_and_Securing_JWT.pdf

  • tokens used for authorization, but not session management
  • short lived (few minutes)
  • expected to be used once (confirm authentication/authorization and get a

session ID)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 5: @HosMercury](https://gist.github.com/HosMercury)

**HosMercury** commented Jul 14, 2021

Copy link Copy Markdown

thanx for the great article

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 6: @Longwater1234](https://gist.github.com/Longwater1234)

**Longwater1234** commented Dec 4, 2021

Copy link Copy Markdown

Definitely. Good old sessions with SECURE, HTTP-only cookies for the win. Best used with Redis store.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 7: @samsch](https://gist.github.com/samsch)

**samsch** commented Dec 5, 2021

Copy link Copy Markdown

Author

@Longwater1234 Unless you have performance issues with your sessions in your primary data store, using Redis is unnecessary added complexity. Also, when using something like the knex connector with express-session, if needed, you can directly query across your session data joined to something like your users table.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 8: @ManasN](https://gist.github.com/ManasN)

**ManasN** commented Apr 12, 2022

edited

Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link Copy Markdown

Hi, I've been reading about this since couple of days and every-time I feel like I am back to square one whenever I try to implement something real.

suppose I want to develop a backend API for mobile applications. It need not follow REST as per religion. I will be using a single centralised server to keep track of everything. Basically a cruddy TODO app with users and roles.

Also, please consider that I am by no means a security expert. Just a developer who wants to collect the paycheque while delivering reasonably secure system. How would I go about doing that in day-to-day development in a secure way? Are there any frameworks/libraries that use cookies to persist sessions on mobile applications? Please help.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 9: @samsch](https://gist.github.com/samsch)

**samsch** commented Apr 12, 2022

Copy link Copy Markdown

Author

@ManasN There's no practical difference for the backend between mobile and web apps. You can use exactly the same tools and follow the same steps and rules as for web when building for mobile.

The difference with mobile is that you don't have CSRF to deal with anymore (though you might want to ensure you can't make cross-origin requests via browser anyway, like by always requiring a matched Origin header (something you can easily include on mobile but the browser controls for web)), and that cookies are "just headers" to a basic http client (though you may be able to use a client which automatically handles cookies in a browser-like way as well). As long as the cookies are sent back with each request (to the correct domain! make sure you don't send _all_ cookies with _all_ requests!) similar to what a browser does, that's all you really need on the client-side.

Most web frameworks for platforms/languages other than Node will includes a built-in (or at least integrated) cookie-based sessions mechanism that you can turn on (or leave on by default) and use for your autht system. Some frameworks have full simple autht systems ready to go out of the box (e.g., Laravel). For Node, the best tools are express-session (and appropriate DB connector) with Express, but you will need to build the login system on top of it.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 10: @kishoreandra](https://gist.github.com/kishoreandra)

**kishoreandra** commented Sep 22, 2022

Copy link Copy Markdown

Thanks for info samsch 🙏, the video by R Degges is 🔥 JWT 0 - 100 Session 😉

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 11: @arantisi](https://gist.github.com/arantisi)

**arantisi** commented Feb 22, 2023

Copy link Copy Markdown

hello im new to spring security. and with spring boot 3 just being released. is there any example code base to look at with a restful api? thank you

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 12: @seiwonpark](https://gist.github.com/seiwonpark)

**seiwonpark** commented Mar 17, 2023

edited

Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link Copy Markdown

Thank you for sharing this article. And here's the reason for `Google does not use JWTs for user sessions in the browser. They use regular cookie sessions` on its **Security** section

``` For example, cookies called ‘SID’ and ‘HSID’ contain digitally signed and encrypted records of a user’s Google Account ID and most recent sign-in time. The combination of these cookies allows Google to block many types of attack, such as attempts to steal the content of forms submitted in Google services. ```

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 13: @omidp](https://gist.github.com/omidp)

**omidp** commented Apr 2, 2023

Copy link Copy Markdown

As far as I can remember I stopped using sessions because it was **hard to scale**. clustering your webserver is cumbersome even when you are lucky enough that your webserver implements it right that's why the extra layer of complexity of adding a distributed cache is required in large scale app. I prefer to use Hazelcast or Redis.

Cookie sessions and local storage also have their own downsides.

You don't have to put sensitive info in JWT. You can put an identifier / user id in a JWT token and retrieve those data from cache by using that identifier.

I wouldn't say Stop using JWT, I would say use it in a right way.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 14: @samsch](https://gist.github.com/samsch)

**samsch** commented Apr 3, 2023

Copy link Copy Markdown

Author

@omidp Refer here: http://cryto.net/%7Ejoepie91/blog/2016/06/19/stop-using-jwt-for-sessions-part-2-why-your-solution-doesnt-work/

If you can retrieve your user from the cache, you can retrieve a session for the same (probably cheaper, actually) "cost".

There _is no right way_ to use JWTs for sessions. Like, it's not an opinion, it can be objectively and logically shown.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 15: @dragosstancu](https://gist.github.com/dragosstancu)

**dragosstancu** commented Jul 21, 2023

Copy link Copy Markdown

funny how cryto.net is over http :)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 16: @LrsK](https://gist.github.com/LrsK)

**LrsK** commented Apr 23, 2024

Copy link Copy Markdown

Another note on CSRF being less of a problem these days: https://github.com/gnat/csrf-starlette-fastapi#why-you-may-not-need-a-csrf-middleware-in-2022

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 17: @Dev-Dul](https://gist.github.com/Dev-Dul)

**Dev-Dul** commented Jun 8, 2025

Copy link Copy Markdown

My main issue with JWTs is just how manual they make everything, you literally have to do everything yourself. You have to issue access tokens, refresh token, validate this tokens, all while making sure your client sends its access token with every request and don't forget that you also have to tell it when where and how to send its refresh token to get a new access token. You don't get this headache from sessions.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 18: @mindplay-dk](https://gist.github.com/mindplay-dk)

**mindplay-dk** commented Oct 15, 2025

Copy link Copy Markdown

JWTs should not be used for keeping your user logged in.

Thank you for maintaining this page, I've come back to this issue dozens of times over the years.

Could you maybe say something about what JWT's _are_ for?

This page, and that "Stop using JWT for sessions, part 2" article with the diagram are great explaining why you _shouldn't_ use them for sessions - but maybe some people would have an easier time getting the point, if you could also provide examples of when JWTs _could_ be used?

I'm not a security expert, so to the best of my understanding, these tokens were mainly designed as a single sign-on solution, is that right? Like, "authenticate here, sign in there"? So you can log in to 100 different Google products in one place, but the JWT you receive is very short-lived and is literally just used the moment after you sign in, to pass to another product/server to prove that you signed in, and then from there on our your session with that product is a regular session-cookie. Do I have it right? 😅

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 19: @vcarl](https://gist.github.com/vcarl)

**vcarl** commented Oct 16, 2025

Copy link Copy Markdown

Close, your browser/client makes requests with a session identifier, the details of which get verified by the auth server. That verification returns a JWT, which can be inspected by internal services to verify that it was made with valid credentials. So your client maintains a classic session cookie (or other secure storage if not a browser), and the auth portion of your backed validates it and issues a JWT that can be statically verified from as other parts of the large and complex backend system are called on to complete the request.

The problem this solves is, if your request fans out into a bunch of calls to internal services, validating the identity of the requestor would require each of those requests to check for a valid session in the auth server. The JWT is used _instead of_ calling back to the auth server to verify the contents of the session db, and since that proof only needs to last as long as the request takes to process, it can have a short lifetime.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 20: @mindplay-dk](https://gist.github.com/mindplay-dk)

**mindplay-dk** commented Oct 19, 2025

Copy link Copy Markdown

The JWT is used _instead of_ calling back to the auth server to verify the contents of the session db, and since that proof only needs to last as long as the request takes to process, it can have a short lifetime.

@vcarl so it's really more of an optimization for microservices than anything else? like, if a client (say, the youtube player) needs to go to 5 different services for all the bits and pieces that make up your personalized home page, it first obtains a short-lived JWT, and then submits that with every request to 5 different servers? which then don't need to reach out to a central auth server - so you validate once for a "group" of requests, likely related to the same operation, instead of each server needing to do it individually?

I can understand why this gets confusing, since really the only difference between that and what most people are doing, is the JWTs are very short-lived and reissued more frequently? 🤔

I mean, there's no reason you couldn't do this in a system with just one service, but it wouldn't really be an optimization. Unless maybe requests to that one service are super frequent, and you're happy with, say, auth happening every minute instead of every second?

But it's not going to make much sense in a monolith with a single backend, I guess? It would have the session store right there in the same DB as whatever you're requesting, so in that case, it's likely just useless complexity?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 21: @samsch](https://gist.github.com/samsch)

**samsch** commented Oct 19, 2025 via email

Copy link Copy Markdown

Author

@mindplay-dk in vcarl's example, the JWT isn't issued to the client. the client makes all its requests to a single service that authenticates the client using the session ID from the cookie, and then that server makes internal requests using a JWT to the other various servers to create the response. the thing is, you don't need a JWT for that either. Internal requests can have more trust, so you only need an API key (updated the same way the JWT verification key would be) and then the auth content can be included in the request. Your example of sending the JWT back to the client is a more realistic case where a JWT could be useful, but usually it would only be for a single request to something like a download server. The majority of web apps don't need and probably shouldn't be using JWTs at all. Also IIRC, joepie91's part 1 article also has the example of when a signed token is useful. It also still recommends not using JWTs because the spec is bad, and there's options which are strictly better technically.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 22: @mindplay-dk](https://gist.github.com/mindplay-dk)

**mindplay-dk** commented Oct 19, 2025

Copy link Copy Markdown

in vcarl's example, the JWT isn't issued to the client. the client makes all its requests to a single service that authenticates the client using the session ID from the cookie, and then that server makes internal requests using a JWT to the other various servers to create the response.

yeah, that does sound extra pointless - though rereading his response, I can't tell if that's what he meant.

if you really want to get this message fully across to the world, I think sequence diagrams might be the safe bet? show examples of precise scenarios of The Good, The Bad and the Pointless™ - these things are way harder to precisely describe or take in as prose. 😅

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 23: @yuriy-yarosh](https://gist.github.com/yuriy-yarosh)

**yuriy-yarosh** commented Jun 16, 2026

edited

Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link Copy Markdown

JWT on it's own is pretty pointless... and nothing prevents people from storing JWE encrypted JWT tokens as httpOnly session cookie.

To get things right you'll need to understand JOSE https://www.youtube.com/watch?v=-8qZpEtENyY

https://auth0.com/blog/demystifying-jose-jwt-family/

There's also WebAuthn https://webauthn.io/ and Fido Passkeys https://www.passkeys.com/

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 24: @Karl-Styner](https://gist.github.com/Karl-Styner)

**Karl-Styner** commented Jun 17, 2026

Copy link Copy Markdown

An opinion focused solely on the web browser environment.

Regardless of whether this opinion is right or wrong, or whether it has value,

I believe that if there is no efficient alternative for a login retention method for native apps on mobile devices, the scope should be clarified.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 25: @julian-di](https://gist.github.com/julian-di)

**julian-di** commented Jun 17, 2026

edited

Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link Copy Markdown

from storing JWE encrypted JWT tokens as httpOnly sessi

except the 4kb cookie limit on most modern browsers (i ran into this)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 26: @julian-di](https://gist.github.com/julian-di)

**julian-di** commented Jun 17, 2026

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 27: @Karl-Styner](https://gist.github.com/Karl-Styner)

**Karl-Styner** commented Jun 17, 2026

edited

Loading

Uh oh!

There was an error while loading. Please reload this page.

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.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 28: @mrx23dot](https://gist.github.com/mrx23dot)

**mrx23dot** commented Jun 17, 2026

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.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

![Image 29: @sohanmaheshwar](https://gist.github.com/sohanmaheshwar)

**sohanmaheshwar** commented Jun 17, 2026

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.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

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

Footer

[](https://github.com/) © 2026 GitHub,Inc.

Footer navigation

You can’t perform that action at this time.

← latest Signal