24 comments

  • solatic3 hours ago
    Necessary qualifier: for browser-based user sessions.<p>Plenty of good uses for JWTs for service-to-service communication.<p>edit: I read some of the linked stuff, e.g. <a href="https:&#x2F;&#x2F;paragonie.com&#x2F;blog&#x2F;2017&#x2F;03&#x2F;jwt-json-web-tokens-is-bad-standard-that-everyone-should-avoid" rel="nofollow">https:&#x2F;&#x2F;paragonie.com&#x2F;blog&#x2F;2017&#x2F;03&#x2F;jwt-json-web-tokens-is-ba...</a> . Please, if JWTs are such a horrifically insecure standard, go ahead and publish your means for hacking AWS STS&#x27;s AssumeRoleWithWebIdentity , or don&#x27;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? &#x2F;sarcasm
    • RagingCactus2 hours ago
      &gt; Necessary qualifier: for browser-based user sessions.<p>&gt; Plenty of good uses for JWTs for service-to-service communication.<p>This is the sensible conclusion right there. I agree JWTs are the wrong tool for the use case of user sessions in the browser.<p>To give some more arguments:<p>All the signature and encryption stuff in JWTs is complex. While common JWT libraries have now mostly got their stuff together, this has not always been the case. There were plenty of libraries accepting the &quot;none&quot; algorithm [1] or allowing attackers to forge tokens by using a public key as a shared secret [2]. This is the direct result of the complexity criticized in the linked blog post.<p>JWTs also cannot do some stuff you want for user sessions. You can&#x27;t invalidate them without keeping a revocation list somewhere. But if you have to check an identifier for revocation on every request you could just use an opaque session ID and look that up on every request instead! Sure, you can use short-lived tokens and refresh them all the time, but why bother with that for a typical application that has to keep some state anyway?<p>All that being said, I wholeheartedly agree that there are use cases in distributed systems and machine-to-machine communication where signed tokens can be useful. Just please don&#x27;t confuse the two cases.<p>[1] <a href="https:&#x2F;&#x2F;nvd.nist.gov&#x2F;vuln&#x2F;detail&#x2F;cve-2022-23540" rel="nofollow">https:&#x2F;&#x2F;nvd.nist.gov&#x2F;vuln&#x2F;detail&#x2F;cve-2022-23540</a><p>[2] <a href="https:&#x2F;&#x2F;nvd.nist.gov&#x2F;vuln&#x2F;detail&#x2F;CVE-2024-54150" rel="nofollow">https:&#x2F;&#x2F;nvd.nist.gov&#x2F;vuln&#x2F;detail&#x2F;CVE-2024-54150</a> (just a random example from googling, I don&#x27;t know what library made this one infamous)
      • nine_k2 hours ago
        &gt; <i>if you have to check an identifier for revocation on every request you could just use an opaque session ID and look that up on every request instead!</i><p>One reason could be the size. A revocation list only needs to keep session IDs of recently logged-out sessions, for which the token&#x27;s TTL hasn&#x27;t yet expired. It may be a much smaller list than a list of every active session.<p>Also, a JWT (or a Macaroon, etc) can store a large amount of details about the session in a cryptographically secure, unforgeable way. This rids you of the necessity to store all that in your active session database, again cutting the size.
        • agwa1 hour ago
          As someone who operates a PostgreSQL database containing 27 billion SSL certificates, each 1-2kb each, with a bunch of secondary indexes that get inserted in random order, I find it pretty incredible that people see the need to optimize their session database. At what scale does the size of the session database actually matter?<p>Those stateless tokens may be &quot;unforgeable&quot;, but they are replayable, and if you&#x27;re not mindful of that you can have security vulnerabilities.
          • mewpmewp229 minutes ago
            I think one meaningful case is when you have services in very different locations and you would rather than having to make a request to a session store in a single location, replicate the data to each location for better latency, so in this case a revocation list.
          • hparadiz1 hour ago
            You should do some basic optimizations. Fixed length table and indexes on the unique string for fast lookups. I also like to do a rolling delete for old sessions after 30 days unless mobile session that is logged in. Those get to live forever.
            • agwa1 hour ago
              Fair enough, but those optimizations are basically free. People think stateless tokens are free but they really are not.
              • hparadiz1 hour ago
                The cost of the stateless token is basically the CPU usage for signing the message and checking the signature with the public key on the client. Example: Google Compute Instance asks metadata server for OIDC token (which is a JWT). The metadata server respond with the token that basically says &quot;here&#x27;s the machine service account, here&#x27;s the machines ID, this token is proof that I am service account abc123 and it&#x27;s valid for 20 seconds&quot;. This is one of the most common uses of JWTs in enterprise. You don&#x27;t store them. They actually are free.<p>Lots of web devs get tricked into using them as primary session tokens and it&#x27;s a huge anti pattern. I see it all the time and people get aggressive about it.
                • agwa1 hour ago
                  The cost is the vigilance required to use them safely. It&#x27;s not just compute&#x2F;storage costs.
                  • hparadiz21 minutes ago
                    I didn&#x27;t downvote you. You&#x27;re absolutely right. Implementation of anything is work.
      • chuckadams20 minutes ago
        A revocation list defeats the purpose of JWTs. If you find yourself needing one, JWTs were probably the wrong choice to begin with.
      • robertlagrant1 hour ago
        &gt; While common JWT libraries have now mostly got their stuff together, this has not always been the case. There were plenty of libraries accepting the &quot;none&quot; algorithm [1] or allowing attackers to forge tokens by using a public key as a shared secret [2]. This is the direct result of the complexity criticized in the linked blog post.<p>I&#x27;m a bit surprised at this. These are extremely simple to solve - the first time I ever did a JWT-reading implementation I specified the right defaults, which are very simple, even for a mid-level backend person I would say, and they haven&#x27;t needed changing in 8 years or whatever it&#x27;s been. It really isn&#x27;t very complex.
        • agwa1 hour ago
          You would think so, but even an <i>authentication</i> company screwed it up:<p><a href="https:&#x2F;&#x2F;cybercx.co.nz&#x2F;blog&#x2F;json-web-token-validation-bypass-in-auth0-authentication-api&#x2F;" rel="nofollow">https:&#x2F;&#x2F;cybercx.co.nz&#x2F;blog&#x2F;json-web-token-validation-bypass-...</a>
      • LgWoodenBadger1 hour ago
        Come on, it’s not like the two are even within the same magnitude or three<p>“But if you have to check an identifier for revocation on every request you could just use an opaque session ID and look that up on every request instead!”
      • hparadiz1 hour ago
        If you don&#x27;t understand conceptually how to verify a signature with a public key the very first thing you should do is get that working and then work from there. It&#x27;s completely unacceptable to ship without this.
    • kyrra2 hours ago
      JWT used to be bad due to libraries with poor defaults. Downgrade attacks were fairly common a number of years ago.<p>Since most of the common libraries across all languages have gotten more sane defaults, it actually is pretty secure nowadays.
      • tptacek1 hour ago
        If we stipulate that, we&#x27;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.
    • jeltz1 hour ago
      I agree with your first part but your edit is a logic fallacy. I don&#x27;t need to be able to hack something to say that it is insecure.<p>For example: I don&#x27;t know how to exploit SAML but I know it is a terrible standard dur to making all of the XML parser an attack surface. I am not a security researcher so I dont know how to find exploits in XML parsers but I know having a huge attack surface is bad.
    • tptacek1 hour ago
      There is in fact a long lineage of vulnerabilities caused by JWTs in real applications.
  • littlecranky671 hour ago
    In 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.<p>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.<p>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&#x2F;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 &quot;Logout from all devices&quot; pattern, where that action will simply set a user&#x27;s minimum_issued_at field to $NOW. All previous tokens will thus be revoked, without individuall revocation list checks.
    • vidarh1 hour ago
      The moment you have to look up the user object, you&#x27;ve lost the primary advantage of JWT, and might as well ditch it.
      • joshmarlow1 hour ago
        It definitely violates DRY but if you keep passing the JWT down the call chain, you can do redundant permission checking in your business layer.<p>Now the reasonable response to the above is that this should be happening in a dedicated authn&#x2F;z concern - and that is correct! But when paranoia is called for, it&#x27;s not unreasonable to have redundant checks in logic where authz is critical.
      • littlecranky671 hour ago
        Depends on the system. If you use JWTs for authentication only, they still serve a purpose. Sessions also only serve as authentication, not authorization. Authorization is independent of the both systems, and it depends how you implement that.<p>There are systems where the authorization is done in the JWT too (i.e. scopes&#x2F;permissions in the token) - in that case you are right.
    • jpalomaki1 hour ago
      Session data lookup is one select to database that gives 0..1 rows and uses index. In most cases this is not something you need to worry about.
      • mewpmewp221 minutes ago
        If you have multiple services in multiple locations however, you may want to replicate this data, so in this case revocation list as it&#x27;s much smaller would be far easier to replicate for much less latency overhead.
      • littlecranky671 hour ago
        I agree. The storage space, however, is a different story. Your session DB can grow huge, depending on your session lifetime and your users logout behaviour. Plus, it is a concern in a distributed system (i.e. a token can be validated on every node, vs. a session lookup must be globally in sync)
      • matt-p1 hour ago
        Can even put it in redis too, if you have performance issues from looking for it in memory then you have probably have more users than google.
        • littlecranky671 hour ago
          What if you have two servers, one in japan and one in central europe? Where do the sessions live?<p>With JWTs, you would only need to replicate your revocation list of the last X hours (X being your JWT default lifetime) and probably be in the megabytes for the total list. Easy to replicate that ever 5-10seconds to all your locations.
    • zsoltkacsandi1 hour ago
      &gt; JWTs have a limited expiry timestamp, so you only ever need to maintain a revocation list for tokens not expired yet.<p>Sessions have expiration timestamps too, and you can configure them however you like.
      • littlecranky671 hour ago
        Yeah of course, but how does that relate to my point? With JWTs you don&#x27;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.
        • zsoltkacsandi1 hour ago
          &gt; With JWTs you don&#x27;T have a list of valid tokens as state, but only a list of invalid ones (revoked).<p>Yes, and a lookup operation is a lookup operation.<p>Your database or data structure used for storing the sessions&#x2F;JWT revocation entries won&#x27;t really care whether you look for things that are active or things that are inactive&#x2F;revoked. If you store it in the right database, both lookups will be O(1), so it is the same (or at least the difference is negligible), regardless of the size.
          • littlecranky6747 minutes ago
            The story changes if you have a <i>distributed</i> database. replicating a smaller revocation list (that is append only) that will never be more than a couple of MB, is easier to do accross distributed nodes around the world than keeping a larger, session state db replicated. Heck, your revocation list can even be public (it contains only a list of substring of a few bytes of hashes).<p>Syncing sessins can be done, no question, I would just think JWT+revocation db is easier to implement, yet robust.
        • doctorpangloss1 hour ago
          isn&#x27;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&#x27;re just going from N to N-1&gt;1, you haven&#x27;t materially decreased your statefulness
          • littlecranky671 hour ago
            But the revokation list is always going to be orders of magnitude smaller than the list of active sessions.
            • doctorpangloss23 minutes ago
              that may be, but who cares how big or small it is really<p>if you are facebook sized, with 1b+ active sessions versus an alternative with 10m+ revocations... the kind of applications that reach this scale, they have enormous amounts of state anyway.
              • littlecranky674 minutes ago
                Everybody thinks Mag7 scale, but actually it is more relevant if you are a tiny webservice - but available world wide. If you need to match each and every http request from a user half way around the world against a central db, you can&#x27;t beat the speed of light. If you can do authentication on each downstream server directly using crypto and JWT validation, you at least save that roundtrip to the session db. The revocation list is tiny (a few megabytes tops), append-only, can be public to the world, and thus easy to replicate to your downstream nodes.<p>If you are a smaller gig, you won&#x27;t have to bother with replicating your sessions and keeping them in sync globally.
  • tracker12 hours ago
    JWTs are insecure... even when using trusted, rsa&#x2F;ppk based signing methods? not shared secrets.<p>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&#x27;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.<p>Lastly, I prefer to have identity&#x2F;auth separated from the application&#x2F;api services... it externalizes context and JWT per request is easier to deal with than some shared cache&#x2F;state system that may intermittently fail as opposed to a signed token that you can verify the signature against known authorities.
    • hparadiz2 hours ago
      You 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.<p>OIDC tokens are all JWTs btw.
      • tracker11 hour ago
        If 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&#x27;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.
        • hparadiz1 hour ago
          You 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&#x27;s login becomes invalid. Using JWTs for this use case is just plain wrong.
  • BlackFly10 minutes ago
    If 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.<p>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.
  • ApolloFortyNine3 hours ago
    This links to some other blog post for the bulk of it&#x27;s &#x27;why&#x27;, and that blog post mostly seems to be annoyed about &quot;You cannot invalidate individual JWT tokens&quot;. Which every time I&#x27;ve implemented, the general guideline is to check for invalidated nonces somewhere. Which resolves that random blog posts second point too.<p>&gt;The JWT specification itself is not trusted by security experts.<p>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.<p>Overall, I don&#x27;t know what I expected clicking a random gist link.
    • tracker12 hours ago
      Yeah... some early implementations just allowed for any authority to be set in the header and trusted it... that&#x27;s of course wrong from the start... if you only allow for trusted or &quot;known&quot; authorities a lot of the contextual concerns become non-concerns.<p>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.<p>JWTs are incredibly useful for separating&#x2F;reusing an access authority from your applications&#x2F;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&#x27;t use shared secrets and I wouldn&#x27;t use long lived tokens... but short lived, ppk signed tokens from verified&#x2F;known sources are generally fine.<p>For that matter, it&#x27;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&#x27;s a short &quot;sak.&quot; 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&#x27;t breach auth.<p>Even then, an API key leak is far mroe likely than a problem with a well implemented JWT solution.
    • jotato2 hours ago
      &gt; &quot;You cannot invalidate individual JWT tokens&quot;. Which every time I&#x27;ve implemented, the general guideline is to check for invalidated nonces somewhere. Which resolves that random blog posts second point too.<p>100% agree. This is common sense to me and I&#x27;m always surprised to re-learn people don&#x27;t do this
      • hparadiz2 hours ago
        Not checking the signature on every single JWT is the same as storing a password in plain text.
  • blixt36 minutes ago
    JWTs are fine, seems a bit sensationalist title...<p>Some nice topics to talk about instead:<p>- When to use an encrypted value (and symmetric or asymmetric), vs. a random (but secret) value, vs. a signed value (readable but not tamperable)<p>- Where to put these values (memory, localStorage, cookies)<p>- How to make sure these values don&#x27;t last forever, and whether you need to be able to revoke them (make them invalid before their natural expiration timestamp)
  • Grollicus2 hours ago
    I&#x27;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.<p>I don&#x27;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.
  • miiiiiike2 hours ago
    Security doesn&#x27;t start or end with JWTs.<p>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.<p>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.<p>Tokens are dropped from the revocation list once the original access token&#x27;s TTL has passed. Which should be low. I use 5 minutes. Most sessions on my site last 4-10 minutes.<p>Worst case scenario, a malicious user is able to access certain read-only resources for a few minutes.
    • zdragnar54 minutes ago
      &gt; look for the JWT access token in a revocation list that is only accessed during sensitive, infrequent, requests<p>I&#x27;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&#x27;s far safer to just assume <i>literally everything</i> about your users needs maximum security.
  • adamddev142 minutes ago
    I remember learning to make sites back around 2019 and seeing so many blog posts and hype around JWTs. It seemed like &quot;this was the way to do it!&quot; But I couldn&#x27;t understand why session cookies weren&#x27;t the better, simpler solution. I just used session cookies. Nice to be vindicated in retrospect.
  • lucassz52 minutes ago
    &gt; You can&#x27;t securely have truly stateless authentication without having massive resources, see the cryto.net link above.<p>I don&#x27;t think the cryto.net post really explains why this is true (at least in a way that would be made different by &quot;massive resources&quot;).
  • feelingsonice2 hours ago
    PASETO is great but there&#x27;s not enough ecosystem support
  • vova_hn22 hours ago
    One of the articles that TFA links to [0] contains the following paragraphs:<p>&gt; 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.<p>&gt; You are essentially powerless, and cannot &#x27;kill&#x27; 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.<p>I&#x27;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.<p>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.<p>[0] &quot;Stop using JWT for sessions&quot; - <a href="http:&#x2F;&#x2F;cryto.net&#x2F;~joepie91&#x2F;blog&#x2F;2016&#x2F;06&#x2F;13&#x2F;stop-using-jwt-for-sessions&#x2F;" rel="nofollow">http:&#x2F;&#x2F;cryto.net&#x2F;~joepie91&#x2F;blog&#x2F;2016&#x2F;06&#x2F;13&#x2F;stop-using-jwt-fo...</a>
    • littlecranky672 hours ago
      &gt;&gt; You are essentially powerless, and cannot &#x27;kill&#x27; 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.<p>&gt; I&#x27;m not sure that this is entirely true.<p>You can be sure it is not true, because it is utter BS. JWTs have an &quot;iat&quot; 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 &lt; $NOW for that identity.<p>I have JWTs implemented for a site and in my case, users cannot individually revoke tokens - but they have a &quot;Signout from all devices&quot; option. That will basically just set a field &quot;minimum_issued_at&quot; 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.<p>Revocation lists have their purpose, though, in systems with heightened security requirements.
      • vova_hn22 hours ago
        &gt; your validation logic simply should refuse any token before $NOW.<p>Well, this approach throws out a lot of babies with the bathwater. You invalidate tons of legitimate tokens along with the one that you wanted to invalidate and get a thundering herd [0] of clients wishing to re-authenticate.<p>This is probably not good in case of a really high load.<p>And if you don&#x27;t have a really high load, then there is no good reason not to have a stateful session storage.<p>[0] <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Thundering_herd_problem" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Thundering_herd_problem</a>
        • littlecranky672 hours ago
          I edited my comment after I posted it to clearify you do this on a per-identity basis. I.e. every user&#x2F;identity has a minimum_issued_at field. A user can &quot;sign out from all devices&quot;, and that will simply update minimum_issued_at with $NOW.<p>You are not throwing out a lot of babies with the bathwater if you would do it in a case of a known attack. You would invalidate ALL tokens of a user, which is a sane default especially since usually you wouldn&#x27;t be able to rule out what other tokens were compromised. And yes, if it later turned out ALL your users and all their token were possibly compromised because you had some kind of security flaw, setting a global minimum_issued_at is exactly what you would do after you fixed the flaw. And yes, that means all your users must reauthenticate.
          • vova_hn258 minutes ago
            Thanks for the correction, I didn&#x27;t think about this approach and it sounds like it should work.<p>The only comment that I have that if you are already querying users table (or collection in case of NoSQL or whatever), you might as well have a sessions table&#x2F;collection in the same database&#x2F;storage and query them together. It seems that difference is not that big.<p>The purported advantage of stateless sessions is that you can check the auth without querying the main db&#x2F;storage (maybe only querying a smaller&#x2F;faster axillary storage).
            • littlecranky6730 minutes ago
              Think a small (as in client base), but distributed system - i.e. Asia&#x2F;EU&#x2F;US locations of a webshop. You can easily replicate&#x2F;cache your products from a central server, and reuse the cache from the localized ones. But each and every web request would have to be authenticated against a central db somewhere around the world. It is just easier if each node can just validate the JWT themselves by using crypto. All they need to do is maintain a revocation list locally. Now, your revocation list is append-only, can be publicy available and never going to be more than a couple MB. Very easy to replicate&#x2F;cache this. I can&#x27;t say the same for a session database.
      • megous24 minutes ago
        &gt; your validation logic simply should refuse any token with iat &lt; $NOW for that identity.<p>makes no sense<p>... ok now it does :) your now is not now, but a stored value
    • elcritch2 hours ago
      It really doesn’t seem very hard to have a small invalidation list. Just a redis cache or a simple broadcaster, etc.<p>Does anyone have an example of how they built a JWT revocation service?
      • littlecranky672 hours ago
        See my sibling comment about the &quot;signout from all devices &#x2F; iat&quot; pattern. This is only a few lines of code.<p>If you want to be more fancy and fast, you can use bloom filters to check if a token is in a revocation list.
  • gabrielsroka3 hours ago
    2019
  • cjoelrun2 hours ago
    I ain&#x27;t never gonna stop!
    • InsideOutSanta1 hour ago
      I might stop if somebody linked to an article pointing out an actual problem, rather than making vague and&#x2F;or incorrect&#x2F;misleading assertions.
      • andreyvit56 minutes ago
        Let me bite, as someone who usually hates JWT but sometimes uses it, including for browser auth.<p>Why JWT is bad: it&#x27;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.<p>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&#x27;t read every line of code that runs in your auth.<p>How to use JWT safely:<p>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&#x27;re senior enough to not take random advice from strangers.<p>2. Write your own JWT handling code. It&#x27;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.<p>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&#x27;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).
      • hparadiz1 hour ago
        HN is full of people who don&#x27;t actually fully understand the subject matter speaking confidentiality. And lots of arguing even when they are clearly wrong.
  • hparadiz2 hours ago
    JWTs are for authenticating an already trusted system with another system.<p>Using them as the primary source of truth is an anti-pattern like the blog post is actually saying.
    • NetOpWibby55 minutes ago
      It&#x27;s not a blog post, it&#x27;s a post on Github Gist.
  • misano1 hour ago
    imo instead of random cookie u can carry some data in it and avoid more joins in database why not ?
  • mgaunard2 hours ago
    A whole lot of nonsense from a web guy.<p>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.
  • kobalsky1 hour ago
    I 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&#x27;t like, instead of asking them to use their brains.<p>&gt; they are not secure.<p>They are secure if they fit your risk profile, a blanket statement like this is just disinformation.<p>Don&#x27;t treat your peers like idiots.
  • szmarczak2 hours ago
    No need to stop. The XSS argument also applies when using cookies.<p>JWTs are just tokens like session data but in JSON format. What format you choose to go with doesn&#x27;t matter.<p>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.<p>Also if your website is susceptible to XSS, skill issue, exactly like in the case of SQL injections. That wouldn&#x27;t have happened had people used the right tools and not played with fire.
    • jkrejcha0 minutes ago
      A lot of times local storage is much less secure than using cookies. Cookies have about 20 years of infra built around it (HttpOnly, SameSite, Secure, etc). There&#x27;s some weird parts about cookies, but local storage really shouldn&#x27;t be used for anything security sensitive
    • wccrawford2 hours ago
      I think anything can be abused, and too many people don&#x27;t have a security-first mindset.<p>One of the advantages of JWTs is that you don&#x27;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&#x27;s just a static page, it doesn&#x27;t need to hit any data.<p>The problem then comes that some developers think that makes it secure, and don&#x27;t check the database for revocation before doing anything with the account. Especially not for giving out private data. They <i>might</i> check before changing any data.<p>I think it&#x27;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&#x27;s practically no better than a session cookie, and it&#x27;s got a lot of foot-guns.
    • dariosalvi782 hours ago
      with 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).
      • littlecranky671 hour ago
        This. 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&#x2F;refresh tokens are always exposed to the JS side (not in a cookie using HttpOnly) in any impl. i&#x27;ve seen.
  • hoppp2 hours ago
    What if I put a jwt in a session cookie?<p>The post is not descriptive enough<p>It should explain how to not store JWT instead of just saying JWT is bad.
  • jheriko1 hour ago
    [dead]
  • well_ackshually3 hours ago
    [dead]
  • dzonga4 hours ago
    due to the recent FIFA hack - just a reminder - stop using JWTs
    • dgrin913 hours ago
      The 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.
      • mycall3 hours ago
        h4ckernews 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.
    • tancop1 hour ago
      if you <i>are</i> fifa please keep using them in the most insecure way possible. release the infantino files