14 ms·
Stop Using JWTs
- dzonga 4mo agodue to the recent FIFA hack - just a reminder - stop using JWTs
- dgrin91 4mo agoThe Fifa hack had nothing to do with JWTs, it was because FIFA was doing auth on the client side. They would have had the same issue if they used cookie auth.
- mycall 4mo agoh4ckernews also accessed an Azure Function App that provided direct download URLs for internal FIFA files, including transfer reports and board level data, due to a lack of RBAC access checks.
- efilife 4mo agowhat the hell do you mean they were doing auth client side? how is this possible with infinite budget?
- tancop 4mo agoif you are fifa please keep using them in the most insecure way possible. release the infantino files
- solatic 4mo agoNecessary qualifier: for browser-based user sessions. Plenty of good uses for JWTs for service-to-service communication. edit: I read some of the linked stuff, e.g. https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-bad-standard-that-everyone-should-avoid https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-ba... . Please, if JWTs are such a horrifically insecure standard, go ahead and publish your means for hacking AWS STS's AssumeRoleWithWebIdentity , or don't publish and just exploit it by launching cryptominers in every Fortune 500 production AWS account. Let me know when you inevitably succeed, because JWTs are so insecure, right? /sarcasm
- kyrra 4mo agoJWT used to be bad due to libraries with poor defaults. Downgrade attacks were fairly common a number of years ago. Since most of the common libraries across all languages have gotten more sane defaults, it actually is pretty secure nowadays.
- tptacek 4mo agoIf we stipulate that, we're still left wondering what the utility is of a standard that creates affordances for the insecure defaults, as opposed to just designing it right from the beginning.
- ForHackernews 4mo agoSpec writers and library authors are human? Who knew
- tptacek 4mo agoI don't understand what this is meant to communicate. The standard is either good or it isn't. "Good effort" is not an engineering assessment.
- ForHackernews 4mo agoYour objection is that they should be "designing it right from the beginning" but that applies to all realms of endeavour. The reason they didn't is human frailty. If everyone simply designed everything right from the beginning we would live in nirvana.
- tptacek 4mo agoYou've completely missed my point. I don't even accept the premise of the JWT standard. But the eventual migration to safer default settings, in a format that continues to expend implementation effort to support settings nobody should use, is in fact a practical engineering problem with the standard.
- well_ackshually 4mo ago[dead]
- gabrielsroka 4mo ago2019
- deleted 4mo ago[deleted]
- darylteo 4mo agoThis needs to be so much higher.
- ApolloFortyNine 4mo agoThis links to some other blog post for the bulk of it's 'why', and that blog post mostly seems to be annoyed about "You cannot invalidate individual JWT tokens". Which every time I've implemented, the general guideline is to check for invalidated nonces somewhere. Which resolves that random blog posts second point too. >The JWT specification itself is not trusted by security experts. This feels like it needs more evidence than just one blog post. And that blog post seems to just largely blame bad implementations? Something that will plague any standard. Overall, I don't know what I expected clicking a random gist link.
- tracker1 4mo agoYeah... some early implementations just allowed for any authority to be set in the header and trusted it... that's of course wrong from the start... if you only allow for trusted or "known" authorities a lot of the contextual concerns become non-concerns. Beyond this, you can make shorter lived JWTs just fine in the browser and have the agents self-update. If you use Azure Entra or a number of other providers it works this way in practice... you keep your JWTs relatively short lived (5-15m) and can even check for jti revokation. JWTs are incredibly useful for separating/reusing an access authority from your applications/api systems. You shift the attack surface and do it in a way that can be trusted. We use PPK for lots of things, including SSH all over the world. No, I wouldn't use shared secrets and I wouldn't use long lived tokens... but short lived, ppk signed tokens from verified/known sources are generally fine. For that matter, it's often API keys that are really problematic. Just had to implement them... for me, the API key presents as a Bearer token as well, but there's a short "sak." prefix then an identity part (base64url uuid bytes) followed by a secret as base64url bytes... in the database is the uuid and a passphrase level salt+hash from the secret.. so the api key generated should be treated as a secret and is one-way to the database, so a db breach doesn't breach auth. Even then, an API key leak is far mroe likely than a problem with a well implemented JWT solution.
- jotato 4mo ago> "You cannot invalidate individual JWT tokens". Which every time I've implemented, the general guideline is to check for invalidated nonces somewhere. Which resolves that random blog posts second point too. 100% agree. This is common sense to me and I'm always surprised to re-learn people don't do this
- tracker1 4mo agoJWTs are insecure... even when using trusted, rsa/ppk based signing methods? not shared secrets. JWTs are too long lived... Nothing is stopping you from limiting the JWT lifetime and having a refresh model against an authentication authority... I mean, even if you use cookie based sessions, you're storing somewhere... you can have a jwt valid for 5-15min. 15minutes is roughly the cache timing for many authorization systems including Entra... and even a 5min token with a refresh system can be used fine from a browser. Lastly, I prefer to have identity/auth separated from the application/api services... it externalizes context and JWT per request is easier to deal with than some shared cache/state system that may intermittently fail as opposed to a signed token that you can verify the signature against known authorities.
- hparadiz 4mo agoYou can make a JWT invalid after 30 seconds or even 1 second. You should set an aud (audience) when creating the JWT. Otherwise the signature is crypto-graphically sound. Validate every single JWT every single time with a short lifetime. OIDC tokens are all JWTs btw.
- tracker1 4mo agoIf your talking about a browser context, where the authority is separate from the requesting body, then expiring even at 30s is excessive for user context, let alone every 1s or every request... you're effectively then inflating every single API request into 2 requests... one for a new token, then another to the API being called. This is irresponsible for not much gain in a user-facing context.
- hparadiz 4mo agoYou should not be using them for user contexts at all. The cookie should be the session token and the sessions should be stored on the server side where you can simply delete them and the user's login becomes invalid. Using JWTs for this use case is just plain wrong.
- 4mo ago
- szmarczak 4mo agoNo need to stop. The XSS argument also applies when using cookies. JWTs are just tokens like session data but in JSON format. What format you choose to go with doesn't matter. You can keep storing JWTs in local storage and still be secure. Discord removes it on page load and restores it when the tab is closed. Also if your website is susceptible to XSS, skill issue, exactly like in the case of SQL injections. That wouldn't have happened had people used the right tools and not played with fire.
- wccrawford 4mo agoI think anything can be abused, and too many people don't have a security-first mindset. One of the advantages of JWTs is that you don't have to check your database or filesystem to make sure the the user is valid and logged in. All that data is in the JWT. If it's just a static page, it doesn't need to hit any data. The problem then comes that some developers think that makes it secure, and don't check the database for revocation before doing anything with the account. Especially not for giving out private data. They might check before changing any data. I think it's a really neat idea that is far too easy to mishandle and create a bad situation. It can save a lot of bandwidth and CPU cycles if you have a lot of non-interactive pages and all you need to know is whether to show that the user is logged in or not. But for actually doing anything, it's practically no better than a session cookie, and it's got a lot of foot-guns.
- dariosalvi78 4mo agowith cookies you can restrict them to HttpOnly so that they are not exposed to client-side scripts. This reduces the chances of XSS to access the long-lived access tokens (JWT or session ids).
- littlecranky67 4mo agoThis. I store my JWT in a cookie, and the cookie is of course set to HttpOnly,Secure and SameSite=strict. That basically kills XSS. I do not use openid connect, and one of my pet peeves with OIDC is that the access/refresh tokens are always exposed to the JS side (not in a cookie using HttpOnly) in any impl. i've seen.
- vova_hn2 4mo agoOne of the articles that TFA links to [0] contains the following paragraphs: > And there are more security problems. Unlike sessions - which can be invalidated by the server whenever it feels like it - individual stateless JWT tokens cannot be invalidated. By design, they will be valid until they expire, no matter what happens. This means that you cannot, for example, invalidate the session of an attacker after detecting a compromise. You also cannot invalidate old sessions when a user changes their password. > You are essentially powerless, and cannot 'kill' a session without building complex (and stateful!) infrastructure to explicitly detect and reject them, defeating the entire point of using stateless JWT tokens to begin with. I'm not sure that this is entirely true. Typically, the total number of non-expired issued tokens is much higher than the number of invalidated unexpired tokens. Therefore, if you store only invalidated tokens and delete them when they get expired, you can significantly reduce the amount of required storage and the cost of lookup. Although, in any real application the performance gains will be minuscule (compared to the cost of, you know, everything else. Auth is just a small part) and probably not worth the extra complexity. [0] "Stop using JWT for sessions" - http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/ http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-fo...
- elcritch 4mo agoIt really doesn’t seem very hard to have a small invalidation list. Just a redis cache or a simple broadcaster, etc. Does anyone have an example of how they built a JWT revocation service?
- littlecranky67 4mo agoSee my sibling comment about the "signout from all devices / iat" pattern. This is only a few lines of code. If you want to be more fancy and fast, you can use bloom filters to check if a token is in a revocation list.
- littlecranky67 4mo ago>> You are essentially powerless, and cannot 'kill' a session without building complex (and stateful!) infrastructure to explicitly detect and reject them, defeating the entire point of using stateless JWT tokens to begin with. > I'm not sure that this is entirely true. You can be sure it is not true, because it is utter BS. JWTs have an "iat" timestamp field (issued at) and in the described case that an attacker has a leaked token, your validation logic simply should refuse any token with iat < $NOW for that identity. I have JWTs implemented for a site and in my case, users cannot individually revoke tokens - but they have a "Signout from all devices" option. That will basically just set a field "minimum_issued_at" to $NOW in the database for their user, and any tokens will always be validated against the minimum iat timestamp. That is a good compromise in security and simplicity. Revocation lists have their purpose, though, in systems with heightened security requirements.
- Grollicus 4mo agoI'm right now adding rabbitmq for notification pushing to a website. Using JWT authentication to control where and what clients are allowed to read, with short lifetimes and regular token refresh. I don't see another setup that comes close to the ease of setting this up - add an endpoint that provides jwt tokens to valid sessions, done. With user-individual permissions.
- andy_ppp 4mo agoCompletely, for some things it’s okay to trust the JWT. Nobody is saying let people transfer money or view government secrets with only a JWT and no security in depth. However receiving and potentially sending ephemeral communications seems fine, nobody got hurt in the 30mins the stolen token was valid for!
- deleted 4mo ago[deleted]
- hparadiz 4mo agoJWTs are for authenticating an already trusted system with another system. Using them as the primary source of truth is an anti-pattern like the blog post is actually saying.
- NetOpWibby 4mo agoIt's not a blog post, it's a post on Github Gist.
- cjoelrun 4mo agoI ain't never gonna stop!
- InsideOutSanta 4mo agoI might stop if somebody linked to an article pointing out an actual problem, rather than making vague and/or incorrect/misleading assertions.
- hparadiz 4mo agoHN is full of people who don't actually fully understand the subject matter speaking confidentiality. And lots of arguing even when they are clearly wrong.
- andreyvit 4mo agoLet me bite, as someone who usually hates JWT but sometimes uses it, including for browser auth. Why JWT is bad: it's a cargo cult solving a non-existent issue in a more complicated way than necessary. An HTTPOnly session cookie containing just a random ID is shorter and easier to handle. Why JWT is also bad: a typical way to use it exposes too much attack surface. Almost every JWT library has way too much functionality, supports multiple algorithms, and many people are too sloppy with their dependencies, so you probably haven't read every line of code that runs in your auth. How to use JWT safely: 1. Have a use case that cannot be easier solved with just a random session identifier. For example, one party creates tokens and another unrelated party verifies them. If same party issues and validates tokens, you better have a super high load, unique use case -- but then you're senior enough to not take random advice from strangers. 2. Write your own JWT handling code. It's literally a few lines of code to create tokens and a few dozen to validate. Only implement the exact algorithms and claims you use. 3. In a typical scenario, JWT should still carry something like a user ID which you should immediately verify against a database. Stateless sessions doesn't mean no DB lookups on validation. If you DO authenticate based on the token alone, the token should be super short lived (seconds or single digit minutes).
- hoppp 4mo agoWhat if I put a jwt in a session cookie? The post is not descriptive enough It should explain how to not store JWT instead of just saying JWT is bad.
- feelingsonice 4mo agoPASETO is great but there's not enough ecosystem support
- deleted 4mo ago[deleted]
- ForHackernews 4mo agohttps://www.paseto.io/ https://www.paseto.io/ expired cert on their website that's how popular it is
- user3939382 4mo agohttps://github.com/paragonie/paseto-io/issues/55#issuecomment-3289148796 https://github.com/paragonie/paseto-io/issues/55#issuecommen...
- mgaunard 4mo agoA whole lot of nonsense from a web guy. Please, keep using JWTs, they do their job well: giving you an access or ID token that you can pass between applications and trust based on cryptographic signatures from an identity provider.
- miiiiiike 4mo agoSecurity doesn't start or end with JWTs. A user wants to access a read-only resource with an invalid JWT? Envoy bounces it without passing the request through to the backend. Valid JWT? Let the request through without having to look up any session information. No DB, no cache, no session server hit. Fast. A user wants to change a password, email address, or add an authenticator? First, require a password, second, require a second factor. If all of that checks out, look for the JWT access token in a revocation list that is only accessed during sensitive, infrequent, requests like these. If the token has been revoked, 403. Tokens are dropped from the revocation list once the original access token's TTL has passed. Which should be low. I use 5 minutes. Most sessions on my site last 4-10 minutes. Worst case scenario, a malicious user is able to access certain read-only resources for a few minutes.
- zdragnar 4mo ago> look for the JWT access token in a revocation list that is only accessed during sensitive, infrequent, requests I've clearly spent too much time working with data covered by HIPAA because this sentence gave me a brief bit of panic. The vagueness and extent of what it technically covers means it's far safer to just assume literally everything about your users needs maximum security.
- miiiiiike 4mo agoThis is the eternal conversation around auth. “The thing you do doesn’t work for the thing I do.” OK. Use something else.
- nijave 4mo agoYour database can double as the revocation list. You can use a last modified timestamp on the user or a monotonic counter to determine if a JWT is stale.
- jheriko 4mo ago[dead]
- littlecranky67 4mo agoIn sessions vs. JWT revocation lists, there is an argument in favor of JWT revocation lists. JWTs have a limited expiry timestamp, so you only ever need to maintain a revocation list for tokens not expired yet. Given that you probably only have a fraction of JWTs revoked compare to valid JWTs in circulation, you only need to query a very small dataset for each request. When using sessions, your list of valid sessions is probably orders of magnitudes higher that the revocation list - thus the data lookup costs and the storage cost of that statefulness is higher. Plus, the article mentions JWTs are stateless but that is usually not true. You mostly not only validate the JWT, but also obtain a matching identity object (i.e. user details) for each request to see if the user is still enabled/authorized to do whatever he does. You can leverage stuff such as per-user revocation lists, or a minimum_issued_at that will validate any JWT iat field. This allows the "Logout from all devices" pattern, where that action will simply set a user's minimum_issued_at field to $NOW. All previous tokens will thus be revoked, without individuall revocation list checks.
- zsoltkacsandi 4mo ago> JWTs have a limited expiry timestamp, so you only ever need to maintain a revocation list for tokens not expired yet. Sessions have expiration timestamps too, and you can configure them however you like.
- littlecranky67 4mo agoYeah of course, but how does that relate to my point? With JWTs you don'T have a list of valid tokens as state, but only a list of invalid ones (revoked). But the list of revoked tokens in the last X hours (where X is your token lifetime) is always going to be smaller than the list of active sessions given a large enough user base. Hence my original point stands, that the lookup and storage costs are lower than on sessions. Whether or not sessions have session lifetimes does not change the fact at all.
- doctorpangloss 4mo agoisn't it that you must have a revocation list in many cases? if you cannot get from N to 1 or 1 to 0 states, if you're just going from N to N-1>1, you haven't materially decreased your statefulness
- kobalsky 4mo agoI agree that using cookies is better for web sessions but I absolutely despise those using the boogeyman to shoo people away from stuff they don't like, instead of asking them to use their brains. > they are not secure. They are secure if they fit your risk profile, a blanket statement like this is just disinformation. Don't treat your peers like idiots.
- jongjong 4mo agoI've never had any issues with JWT. There's a group of incompetent developers who like to point to a tool as a scapegoat to distract away from their own failure to use the tool correctly. I think the irony is that the people who make these blanket statements may be idiots themselves and that's why they think everyone else is an idiot. They can't imagine that other people don't have problems using those tools. It's a skill issue. Some people here built embarrassingly parallel distributed systems with consistent hashing load balancers. JWT is easy by comparison. To me, it sounds like a child putting their shoes on the wrong feet, getting blisters and concluding that nobody should wear shoes.
- misano 4mo agoimo instead of random cookie u can carry some data in it and avoid more joins in database why not ?
- lucassz 4mo ago> You can't securely have truly stateless authentication without having massive resources, see the cryto.net link above. I don't think the cryto.net post really explains why this is true (at least in a way that would be made different by "massive resources").
- adamddev1 4mo agoI remember learning to make sites back around 2019 and seeing so many blog posts and hype around JWTs. It seemed like "this was the way to do it!" But I couldn't understand why session cookies weren't the better, simpler solution. I just used session cookies. Nice to be vindicated in retrospect.
- blixt 4mo agoJWTs are fine, seems a bit sensationalist title... Some nice topics to talk about instead: - When to use an encrypted value (and symmetric or asymmetric), vs. a random (but secret) value, vs. a signed value (readable but not tamperable) - Where to put these values (memory, localStorage, cookies) - How to make sure these values don't last forever, and whether you need to be able to revoke them (make them invalid before their natural expiration timestamp)
- BlackFly 4mo agoIf I understand the point being made here then the idea is that a stateless session via a cryptographically verified bearer token needs a stateful revocation list to eliminate hijacking (a user logout should completely invalidate the login but a bearer token would otherwise continue to be valid) and if you are maintaining state then you can just use a complete stateful session and avoid the complexity of the cryptography. This point is not made very clearly and is buried by overemphasising JWTs instead of just quickly pointing them out as an example of a stateless session. But yeah, it is a good point.
- bastawhiz 4mo agoRevocation lists can simply be replaced with a "tokens not valid before" field per user. When a user logs out, set the field to now(). Reject JWTs that have an iat less than that value. Am I missing something?
- Sohcahtoa82 4mo agoWhat you're missing is that you're still creating state. You're still having to check a database to determine what the "tokens not valid before" value is for that user. And what if the user is logged in from multiple devices, but only wants to log out from ONE of them? Your solution logs them out from all of them. The entire point is that it is not possible to have authentication that is both: 1. stateless. 2. secure. And so if authN is going to be stateful anyways, you might as well just use an opaque token in a database and eliminate all the complexities and foot-guns of JWTs.
- nijave 4mo agoThere is middle ground. Authn can be stateless and authz stateful. Usually it's impractical to shove all the authz nuance into a JWT anyway Doesn't address logging out a single session, though
- dchest 4mo agoYeah, you made a revocation list but with time value instead of the token value.
- rdegges 4mo ago=0 I stumbled across this post and was thinking that it's interesting to see this topic trending now, since I've done a lot of work on it in the past. Then I clicked through and realized the author is linking to some of my stuff! What a blast from the past. Anyhow, there are way smarter people than myself who have covered this topic extensively over the years, but I still think that, even in 2026, JWTs are the wrong tools for web auth. They're fine to use for service-to-service stuff, but if you have the option, just use PASETO -- it solves a lot of the issues!
- deleted 4mo ago[deleted]
- bastawhiz 4mo agoOne of the linked posts explaining why you shouldn't use JWTs is bizarre at best: https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-bad-standard-that-everyone-should-avoid https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-ba... It boils down to "there were bugs in some of the libraries" and then goes on to recommend you...pull in libsodium and do it yourself??? This is ludicrous advice that I simply can't take seriously. All software has bugs. The whole Internet lost its shit with Heartbleed, but we still use TLS and OpenSSL. > The JWT specification is specifically designed only for very short-live tokens (~5 minute or less). I've never heard this before and can't find any evidence to back this claim up. RFC 7519 doesn't make any such claim.
- EGreg 4mo agoOver the past 15 years of developing secure web apps for various organizations, I ended up architecting solutions which had to deal correctly with ITP, webauthn, CHIPS, iframes and more. This year, I ended up publishing an open protocol that can be used for everything from secure authentication to API requests to micropayments, and it works with the existing Web stack and P256 curve with JSON serialization curves as well as EVM blockchains via K256 curve and EIP712 serialization. I encourage everyone to take a look at it and consider using it, so we can stop reinventing the wheel. Everything has already been deployed, it’s an extremely simple protocol, much simpler than JWT and requires no global registry. https://openclaiming.org https://openclaiming.org https://github.com/OpenClaiming https://github.com/OpenClaiming It is also used in stuff like https://safebots.github.io/Safecloud/ https://safebots.github.io/Safecloud/
- himata4113 4mo agoHmh, the way I usually use JWTs is as an authentication cache. You obtain your authentication token from the auth service which grants you permission to other services. This has several advantages, the main one being that sub-services do not have to interact with the authentication database or have access to the capability to mint tokens (this assumes you use RS256 not HMAC). So if a sub-service gets compromised it's not as devastating as a service which has access to the authentication database. If you have sensitive data inside the token you should use JWEs, although they're not as good because you have to ask an internal service (which has the private key) to decode the token each time you want to use it. My typical layout is {"id": (uuid), "scopes": ["scope:read/write"]}. Also they're really neat for SPA's as you can have your static site server validate that the JWE with the public key before serving any resources. The way I use this is that I have my static site compiled to /(scope)/path and the static service will not serve pages that you cannot access anyway. This is very useful in cases where you have administrative panels where you don't want to expose to users what capabilities your backend has or/and expose the internal service paths that can be attacked. My lifetime for JWT's is around 5 minutes for "backend access", things like /me are cached in localStorage unless explicitely instructed in /refresh to drop localStorage cache. My request handler in my SPA applications detects "refresh required" and refreshes the token. I think most of the blame here belongs to node/next and python libraries. I write my backends in strongly typed languages and my frontend is always made out of precompiled static pages. My current setup for the frontend is using VITE with prerendered pages for landing and normal SPA for applications. With all of that said I strongly disagree with this entire gist. JWT is as secure as you want it to be.
- iririririr 4mo agoirrevocable* cache
- himata4113 4mo agoI've adapted dynamic public-key hotswapping whenever there is a need to revoke tokens as it would simply force all tokens to go to /refresh endpoint instead of the standard 5m cache. Never had to use it though. I've experimented deriving the public key from the uuid so I could broadcast that "keys with this id and this revision should no longer be accepted and should be refreshed", but as I said never ran into a situation where 5 minute expiration wasn't fast enough. That said if you're dealing with critical infrastructure JWEs are the way, you just lose the speed benefits of JWEs as you have to make a request to an internal service to validate and decode, but for everything else JWTs are completely fine.
- _el1s7 4mo agoI hate these type of clickbait articles
- bijowo1676 4mo agoJWTs are in every bit superior to cookies
- ForHackernews 4mo agoI'm not convinced. All the PASETO objections[0] are things that have long since been addressed by every major JOSE implementation. [0] https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-bad-standard-that-everyone-should-avoid https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-ba...
- Aeolun 4mo agoAt this point this just feels like an old man shouting at the clouds.
- waterTanuki 4mo agoEveryone has a strong opinion on how to implement auth yet seemingly no one has hard data or peer-reviewed research to back up said opinions.
- genghisjahn 4mo agoI've used JWTs for a number of server to server interactions and they are amazing for what they are. I've also told many a front end team member to NOT use them.
- stickfigure 4mo agoLike most "always do this" or "never do this" articles, this one is dumb. If you are operating at a scale where you can simply store session data in the database and look it up every time, that's a fine way to operate. At some scale this approach becomes a problem, and it's faster/cheaper/simpler to store some limited data on the client (signed). Yes there are complexities to both approaches. That's fine.
- eranation 4mo agoBeen in this rabbit hole since JWT shipped. As others have mentioned, cookies have their own risks, you're now juggling both XSS and CSRF, and the CSRF defenses (SameSite, tokens) do nothing against XSS since that's a same-origin attacker. Just to clarify, httpOnly/sameSite isn't useless under XSS the way localStorage is. XSS can't read a httpOnly cookie, so it can't exfiltrate the credential, it can only perform the attack during the session from the victim's browser. A JWT in localStorage can be reused offline for its entire lifetime. Also worth separating: localStorage is the exposure, not JWT. Just please for the love of all that's good and pretty, don't store a JWT in a httpOnly cookie.
- Maxion 4mo ago> Just please for the love of all that's good and pretty, don't store a JWT in a httpOnly cookie. Depends on who is saying, I've read the same thing but the other way around. Never store a JWT in LocalStorage and always store it in a httpOnly cookie.
- cyberax 4mo agoStop using JWTs and instead use my copy of JWTs with all the same fundamental issues! But now it also has a custom snowflake serialization format! Yeah, right. JWTs are fine, as long as you use sane algorithms. The missing revocation really can be done by replicating revocation policies. E.g. a direct list of revoked tokens or a blanket "don't trust tokens before this timestamp".
- jongjong 4mo agoJWTs are extremely useful for storing basic non-secret authentication info. Session IDs are not as good for most situations and force unnecessary database or memory store lookups. JWT is a more versatile authentication construct because it doesn't prevent you from doing that extra lookup but it also doesn't force you to. It's far better than a session ID in the sense that you can store an accountId inside a JWT and be confident about the identity of this user... The fact that you can get such confidence without any external lookups; just by looking at the token, is incredibly useful on its own. You can already seperate out unauthenticated guest users from authenticated users and you can tie their identities to real accounts without even checking the DB or session store. Banning is a separate concern. Being able to quickly, efficiently and reliably identify a user from the server-side is a necessity. The only real downside of JWTs which people point to is that they cannot be easily be revoked... But if you really need the ability to revoke quickly, you can easily have 10 minute expiries on your tokens and request refresh every 3 minutes or so... So if you want to ban someone, there would be a 10 minute delay which is acceptable for the vast majority of scenarios... You should handle rate limiting as a separate concern anyway if spam is the issue. For certain systems, a user may be making hundreds or thousands of requests in 10 minutes so you're saving a HUGE number of session ID lookups and it means that you don't need to run and maintain a separate Redis service or whatever else. Not to mention the additional latency which is added when you need to check Reddit before each operation. These blanket statements against JWT are not new. People have been misusing them and blaming the tech because they don't want to acknowledge that they made implementation mistakes. Any technology can be misused. It's foolish to misuse a perfectly good piece of tech and then use that as the basis to promote some alternative which has been through less battle-testing and which probably has even more gotchas which are yet to be discovered. As a senior engineer with 15+ years of experience, I've seen this cycle over and over again. The new tech is always presented as fool proof and it never never never is.
- Aldipower 4mo agoThank you. If done right, JWTs simplify quite some things.
- andy_ppp 4mo agoOkay, so hack into a site that uses JWTs for login, if it’s so insecure we should be seeing loads of attacks against them right? Stolen tokens everywhere being used to impersonate people and other things. For example I believe ChatGPT is using Auth0 which uses JWTs, so you can hack this insecure token system? Should be easy right given the extremity of the warning that JWT is the big problem here.
- mawadev 4mo agoFinally, feels like the blog stirs up unnecessary drama
- Maxion 4mo agoA lot of these type of coding practice debates are theoretical. IMO coding is more-or-less fancy blue collar work. What matters is what works in practice, not what works in theory.
- yencabulator 4mo agohttps://cybercx.co.nz/blog/json-web-token-validation-bypass-in-auth0-authentication-api/ https://cybercx.co.nz/blog/json-web-token-validation-bypass-...
- jcmartinezdev 4mo agoThis is really old. JWTs are very safe.
- yencabulator 4mo agoJWT is a bad spec leading to stupid mistakes all over the ecosystem. "Just be very careful in all of the implementations forever" is a horrible security stance.
- scudsworth 4mo agono
- harrall 4mo agoJWT is secure. I just noticed that after JWT was created, people would just slap on JWT like an end-all because JWT sounded secure and they thought it was all that they needed to do. That’s my only “problem” with JWT but to be honest, people will build insecure systems anyway.
- jongjong 4mo agoExactly, it's like saying that Postgres is insecure because it allows SQL injection attacks when untrusted user input is injected into the query directly.
- asattarmd 4mo agoJWTs are secure in the sense that they are tamper-proof. And that's all you need for a session token (plus the revocation list). There's nothing inherently insecure about JWTs.
- green_wheel 4mo ago> The JWT specification is specifically designed only for very short-live tokens (~5 minute or less). Sessions need to have longer lifespans than that. Citation needed. Where does it say this?
- mekoka 4mo agoEvery once in a while an article with a sensational title against JWTs pops up in here and I have to wonder if something new was discovered. But nope. It always boils down to the same "can't invalidate it" complaint, which can be addressed with a viable deny list structure (simple in-memory or runtime index, bloom filter, trie). Then there are the vague "it's insecure" claims which when looked at closely, come down to "some people use it wrong".
- ChicagoDave 4mo agoOAuth2 has been the web security standard for ten years. I don’t recall any major security announcements about it. The OP is confused.
- tomjakubowski 4mo agoI'm confused. What does OAuth have to do with JWTs? They seem orthogonal: OAuth2 doesn't specify a format for access tokens, nor does it require statelessness.
- ChicagoDave 4mo agoI guess I just assume a good architect would enforce authorization with an identity server and never put anything important on the client.
- Anoian 4mo agoHow does an identity server store auth information with the user?
- jillesvangurp 4mo agoThere are a lot of oauth2 adjacent specifications recommended by the IETF and others that are all about using JWTs in the context of standards like oauth2 and openid connect. You are right that you can do oauth2 without JWTs. But JWTs are a common enough base technology that it is standardized separately under the IETF along with a whole range of related standards. As does the OAuth2 standard and of course a whole range of standards built on top of that and related standards such as OpenID Connect. The base specification does not mention JWTs, mainly because it predates the JWT RFC by a few years. That's something that's being rectified in the v2.1 draft of the spec which recommends the following: > It is RECOMMENDED to use asymmetric (public-key based) methods for client authentication such as mTLS [RFC8705] or using signed JWTs ("Private Key JWT") in accordance with [RFC7521], [RFC7523], and their update [I-D.ietf-oauth-rfc7523bis] (defined in [OpenID.Connect] as the client authentication method private_key_jwt). So, JWT usage is indeed not required, but very strongly related if you look at the broader ecosystem of specifications and implementations. It's hard to ignore JWTs in that context.
- mattstir 4mo agoIs this at all coherent...? The author really seems to be comparing cookies to JWTs as if they exist in the same category, but it really is apples to oranges here. In fact, one of the first articles they link to spell that out explicitly: > A lot of people mistakenly try to compare "cookies vs. JWT". This comparison makes no sense at all, and it's comparing apples to oranges - cookies are a storage mechanism, whereas JWT tokens are cryptographically signed tokens. And yet the author seems not to have noticed, or something? Odd.
- dalton_zk 4mo agoStop using jwt, but what we should use when we have a backend and frontend applications in different servers?
- luckilydiscrete 4mo ago[dead]
- wyc 4mo agoWhat about JWT+DPoP? It would address many of the author's concerns. https://datatracker.ietf.org/doc/html/rfc9449#name-dpop-proof-jwts https://datatracker.ietf.org/doc/html/rfc9449#name-dpop-proo... The JWT specification itself is not trusted by security experts. This should preclude all usage of them for anything related to security and authentication. Very bold claim that seems to ignore all the iteration and hard-won lessons on this from the ecoystem...
- userbinator 4mo agoWhat a bunch of BS... The JWT specification is specifically designed only for very short-live tokens (~5 minute or less). Sessions need to have longer lifespans than that. Huh? The expiry is as long or short as you want. The JWT specification itself is not trusted by security experts. ...and we're supposed to trust some random gist? Pure appeal to authority.
- yieldcrv 4mo ago(2019) and the JWT can transport a more encrypted user session as a value just be intentional
- Aldipower 4mo agoMan, once a year the same BS. JWT in an secure HTTP only cookie are perfectly fine, not less secure then a regular a regular session id, but indeed give you the advantage being able to be stateless!
- smetannik 4mo agoThis debate pops up every few years and the community still seems like don't have a clear consensus
- camgunz 4mo agoI think people were using them to skip hitting the database for an auth check on every request, but revocation is hard, e.g. someone quits, but nothing on the backend of their old company's services is checking their JWTs stored in their browser, so they still have all the access they ever did.
- owaislone 4mo agoJWTs are awesome but they are are being overused by people. People use them in web, on mobile and everywhere in between. Places where cookie or bearer token auth has already solved the problems. JWTs strength is that it can be verified independently without real-time coordination between services. So a service can issue a JWT with auth scopes to a user. The user can take the JWT to any other service and if that service trusts the signer, it'll allow the user access and also get basic user info from the token itself. The service doesn't need to make an API call to the issuing service or even know if/where it exists. That is where JWT is really powerful. For web/mobile auth where same server issues the JWT and same server verifies it, it makes no sense. JWTs cannot be invalidated. If a user loses some permission or account gets disabled, JWT will still be valid until its expiration time. Servers must either make DB calls to verify the user is still active or be fine with deactivated users having access for a while after account is disabled. This completely defeats the purpose and bearer tokens work perfectly for this use case. JWTs should _almost_ never be used in client side auth. Client should send regular cookies and bearer tokens. The auth server can internally generate a short lived JWT and inject it into requests before they get routed to various services internally so those services don't need to query DB every time to verify the user.
- carter2099 4mo ago> Servers must ... make DB calls to verify the user is still active I'm not being facetious, genuinely asking - is this a big deal? Should be a pretty cheap query, and with pooled connections, hardly any overhead.
- owaislone 4mo agoDepends. If you backend is just one service, it is not a big deal but then you don't JWT at all. You just need a regular cookie/token. If your backend is a set of 12 services where each needs to verify the authenticity of the request then it might start adding up. In that case using JWT _after_ the initial API gateway makes a lot of sense. The gateway hits the DB, authenticates the request, mints a JWT and injects it into downstream requests. Then each service on the request path just verifies the JWT. Overall I don't think hitting the DB for auth is a big deal and that is why we don't need all the bells and whistles JWT brings. Just use bearer auth.
- frictasolver 4mo ago[flagged]
- caputchin 4mo agoI'm sorry I fail to see the difference between a cookie holding a server session ID and a cookie holding a JWT token. JWT sessions are created and stored (in some way) in the DB anyway and it's short lived. That's basically a session stored in a DB. When we say no to sessions we only mean server sessions in your backend service as this can't scale horizontally. I feel like this is just a shiny title confusing different approaches and practices.
- arcfour 4mo agoJWTs aren't stored in a backend though. Session cookies you exchange an opaque value with the DB for the user info JWTs the user hands you their driver's license, and you can verify that it's an authentic license for the person who's name is on it
- nijave 4mo agoThe word "session" is overloaded. In browser terminology, a session cookie is one that expires/is cleared when you exit the browser (it doesn't persist on disk) In application terminology, a session is user state that outlives a single request. Depending on what definition you use and how pedantic you are, a stateless signed cookie is also a session cookie.
- nijave 4mo agoAgree, snippet is conflating a lot of things. JWT is a signed JSON blob. Cookie is a storage and transport specification. Local storage is a storage spec. A "regular" cookie could also be a signed cookie which is basically the same thing as JWT. Slight disagree in horizontal scalability--server sessions scale somewhat with Redis, replicated DB but obviously not to the degree stateless ones do. Also on revocability, you don't need to revoke the token if you're validating fine grain permissions outside the token. You can revoke the permissions (ie disable the user). You can use JWT to gate permissions at a high level (infrastructure, traffic edge, API gateway) then validate fine grained permissions in code
- nbevans 4mo agoJWT inside of a cookie is fine. This gist is unnecessarily pedantic and seems oblivious to the fact that 99% of JWT impls are indeed just stuffing it inside a cookie. But yes, short life times with frequent renewals is necessary; that's obvious though. And same applies to any other auth tech.
- disruptiveink 4mo agoThis is stupid/dangerous advice and I will die on this hill. > The JWT specification is specifically designed only for very short-live tokens (~5 minute or less). Sessions need to have longer lifespans than that. Your auth token should be 5 or 10 minutes long, yes. Your session should be encoded in a refresh token, which can be another JWT or completely opaque, whichever you prefer. > "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: No. Stateless auth is completely feasible in a secure fashion. You need short lived tokens as stated above, and to perform instant logout you need to be able to identify JWTs that were invalidated at the level of your API gateway. You don't need to store every JWT that is valid, only a way to identify the ones you want to invalidate early. If you make bulk invalidations not go onto this store (and just accept that with bulk logout, users will remain logged in for up to 5 minutes, which if you're doing logouts in bulk, this does not matter to begin with), then this typically fits in memory. "if you must have a data store, it's better to just store all the data" is just wrong. And of course for refreshing the token, you go to your data store and recompute things. But the point is to do this every 5-10 minutes like the author (correctly) identified, not on every API request. > 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. But no one does this. People use JWTs as auth tokens which are short lived but contain a bunch of information about the users that you'd get in huge trouble if it could be forged (user ids, resolved geolocation, entitlements, cohorts, etc etc), but that you also don't want to make every service of yours look up against a data store or compute for every single API request. It should be data that normally doesn't change during the duration of the auth token. When it does change, you should have a mechanism to immediately invalidate the previous one (see above) and issue a new one on the API call that made the change. Simple. > 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. Yes, all standards are horrible if you look at them long enough. XML is terrible, YAML is terrible, ASN.1 is horrific. I'll take a flawed standard that has been studied and criticized publicly so I have libraries and know where the footguns are vs rolling everything myself and having to find out the footguns on my own.
- YetAnotherNick 4mo agoThere isn't any point in the article or video that describes why it is worse than session token in any way. Personally, I think 5 minute expiry is too long and I think 10-30s expiry is the ideal range, so that one page load requires 1 token. > Sessions need to have longer lifespans than that. Why is this JWT issue. JWTs generally have refresh token, which are database validated and we need to just refresh once for 100s of calls in 5 minute. > "stateless" Yeah this sounds bad and I don't think people do it. > 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. Ok, but it is not worse too. > 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. What are they even trying to say?
- CodesInChaos 4mo ago- commented on the wrong post -
- narinciye 4mo agowrong post
- Ellipsis753 4mo agoYes! JWTs in the browser are a total pain. You need a way to revoke them (when a user is fired, etc). Or you need to make them crazy short lived (5 minutes). Users need to stay logged in without the tab open for a lot longer than 5 minutes, so you need a way to make that work. They tend to be really large, which slows down your load times a lot due to TCP slow-start and people just having weak upload speeds. And they can easily get too large to store as a cookie. Also, people forget that anyone can read the data stored in the JWT. They just cause more problems than they solve and there's a lot of edge-cases and footguns.
- sreekanth850 4mo agoKindly advise how to do auth for a separate service that doesn't have db and is stateless.
- RiOuseR 4mo ago[dead]
- gwbas1c 4mo agoI once got the heebie-jeebies about an API and on instinct ended up protecting an application from the "macOS Keychain Access Control List (ACL) Zero-Day vulnerability". This article just sounds like heebie-jeebies, at best it's someone saying something about JWT doesn't smell right (because it can be used incorrectly,) at worst it's a pissing match / religious war. This article would be more credible if it had a tangible explanation of a real exploit. (BTW: I don't understand how cookies are inherently "better" or "worse." They can be sniffed and replayed too.)
- huangchengsir 4mo ago[flagged]
- Demiurge 4mo ago> 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. This is quite a loaded statement. Why is it better to store all the data? What if you have a CDN layer that only needs to do routing based on authentication or scope, or other token encoded data?
- Manouchehri 4mo agoHear me out: use JWTs as the cookie session value. - Use ES256 - Always set the JTI to be completely random - Set iat (issued at time) and exp (expiration time) - Set iss (issuer) and aud (audience) to match your application - Set sub (subject) to match whatever unique identifier you use for users Store the hash of the JWT in your database with a lazy cleanup hook on the expiration time. Now, you can use this JWT for a cheap WAF at the edge! Token expired already? No need to query the database, reject. Audience doesn't match the requested URL? No need to query the database, reject. Signature doesn't match your public key? No need to query the database, reject. Everything passes? Query the database for the token hash. Token hash not in the database? Add the token hash to the WAF's cache (with lazy cleanup hook on the expiration time). Everything passes but token hash in the WAF cache of rejects? No need to query the database, reject. etc See the benefit? It's defense in depth. If you screw this up, all you lose is the WAF layer.
- sauercrowd 4mo agoThe short term tokens section is weird. > If you do need a short-lived, signed token for something, there is a better spec called PASETO which is designed to be secure Suggesting to non security people (like myself) something for auth that isn't a mainstream idea seems like a bad idea? Not to mention that it doesn't refer any reasons why it's better
- andychiare 4mo agoJWTs were never designed for session management. Their primary purpose is to transfer information whose origin can be verified. Period. The idea that they are related to sessions is, unfortunately, a very common misconception. I wrote an article about this some time ago: https://dev.to/andychiare/sessions-tokens-and-rocknroll-4pdc https://dev.to/andychiare/sessions-tokens-and-rocknroll-4pdc