JWTs are insecure session tokens

25,349
0
Published 2024-05-10
I've often seen hate for JWTs online, but never really understood why they we're seen as badly designed and insecure. So I did some digging and came to my conclusion. Which is that JWTs are a good method of authentication, but bad session tokens.

Basic opaque session tokens are usually the way to go. Using stateless tokens has many added costs, while not providing that many benefits in practice.

All Comments (21)
  • A common practice is to require a hard authentication when making important requests, such as editing a profile or sending a money transfer. This significantly reduces the impact of an expiration vulnerability
  • @m4rt_
    Technically, the reason LTT had a hard time regaining access was because the malware kept grabbing their session tokens every time they reset it. So it wouldn't matter if it was a JWT or a normal session token for this situation, but it's still best to use normal session tokens.
  • I kind of did the same. Statelessness is great on paper but one little mistake and you're f***ed. So opted for identifiers for my JWTs and then storing the identifiers on my server. Defeats the purpose of JWTs though.
  • @DavidAlsh
    So a short lived access_token and revocable refresh_token? This is standard with AWS Cognito, Auth0 or most other OAuth2 OICD providers. Then use step-up authentication (like MFA backed tokens) for important actions
  • JWTs are very strong when used with an asymmetric encryption algorithm like RSA. They are a life saver in microservice environment because each service can verify the token without querying the authorization service.
  • @m4rt_
    Authentication: use JWTs Sessions: Use session tokens in cookies
  • @HeyVSauce
    JWTs with short lifetimes (~10mins), constant refreshes, and an in-memory store of accounts blacklisted for refreshing after a certain timestamp (ie as part of a "cancel all sessions" feature) can help get around this limitation, whilst still limiting calls to a larger db
  • @PASTRAMIKick
    refresh and access tokens sort of fixes the token revocation issue, the short life of the access tokens minimizes the impact of a token that has been compromised
  • @luckbeforeleap
    Some people in the comments are getting confused between (1) the use of JWTs in both OpenID Connect (mandatory JWT usage) and OAuth2.0 (JWTs very commonly issued by IdP as access tokens) and (2) JWTs used as (post-authentication) session tokens for the User's session with the web application. They are very different uses cases for JWTs.
  • @SoloElROY
    Lately I've been thinking that maybe refresh tokens could be a solution to this (I have never implemented them in a project) but just came to realize they are glorified session tokes. I see refresh tokens as a security middle ground between short lived JWT and long session tokens, but in the end you gotta keep state to make them secure. Grat video and great explanation of the use cases!!
  • Thank you for saying it out loud!! I have been saying this for ages. Even Oauth2 uses JWTs once and then the client is left with an opaque stateful access token
  • I personally like using jwts as short lived session tokens (3-5 minutes) and a random string as a refresh token.
  • @more-sun
    Are there examples of the other implementations?
  • Great video. If I recall correctly, Kubernetes Service Account Tokens follow a sort of mixed approach: they create JWTs but these JWTs are bound server side to the Service Account. Therefore, there is a way to revoke access server side by removing the Service Account (which might be overkill depending on how you are using the Service Account) I'm not saying it's the best solution, just sharing other approaches
  • @benlovell9416
    “You may as well use a stateful token” But with stateful tokens you need to make a request to an auth server in the hot path. If instead you load the revoked tokens on each service as they get revoked, then you decouple the user request lifetime and the auth server interaction, since you can keep them in memory at each node. If you are somehow expecting a huge amount of revoked tokens (which probably depends on the expiration dates of the JWTs vs. how many users you have etc), then you can instead ship a bloom filter, check for a hit, and then check the auth server to see if it’s a false positive.
  • @logusgraphics
    I don't see these issues as part of the JWT spec. But more of the particular implementation.
  • @kartonrad
    I always advocate for a revoke_before field on the subject table This should be relatively cheap, if you need to get the subject out of your state anyway And it adds the option to revoke all sessions.
  • @MrFedX
    Great video! Putting solid words on thoughs that didn’t sit right with me.
  • @someguyO2W
    Skil issue. Jwts might be stateless, but that doesn't mean you can't use stateful revocation. A jwt is simply a data container that can be protected against tampering and encrypted. How you're using it might be insecure, but they are not insecure by themselves. You can fully have secure session tokens using Jwts.