Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

With #2, you don't need a 'refresh token', the JWT itself is the refresh token, you can just sign a new one some time before the old one is set to expire. You don't need to store a separate session object on the back end, that's the whole point, just have the valid JWT token attached to the connection or request; if the user has an existing valid JWT attached to their socket or request, you can just use that one as the basis to create and sign a new one with the same data but a new expiry date. I find this works really well with stateful connections like WebSockets (especially since each frame has little overheads in terms of headers). You can re-issue JWTs in real time periodically (e.g.) with short 10 minute expiries or you can make the user request a new one periodically as well. There are pros and cons to either approach though the second one is more common.

So to summarize, JWTs save you from having to store and maintain a session object. You just don't need one. A blacklist or ban list is a lot easier to manage than session data, only a small number of users will be blacklisted. You could also add an isBanned field to the user's account object itself. No need to maintain a separate 'session'.

For log out, you just make the client remove their JWT from wherever they have it stored; e.g. memory, localStorage or sessionStorage. Once all valid signed JWTs have been physically deleted from wherever they were held, the user is logged out.

Even if you consider edge cases; e.g. If an attacker managed to grab hold of a user's JWT just before the user logged out; it begs the question, how did the attacker manage to do that? An XSS vulnerability in your front end? Well, once resolved, you'd probably want to invalidate all your previously issued JWT tokens (for all users) by changing your auth signing key on the back end... Just to be safe right? It's kind of neat that you can invalidate all previously issued JWT just by changing the signing key. It's instant and doesn't cost any resources unlike deleting large numbers of session objects from a datastore.

I can't think of any situation where you'd urgently want to invalidate a single JWT/session that couldn't be handled better by adding a single isBanned field to an account object or via some kind of IP blacklist. If you're using sessions with session IDs and the user is banned, you'd want to add some kind of flag to their account object itself right? Not just the session... With JWTs, you just need this flag to exist in 1 place, not 2.



Consider the scenario where your user goes offline for more than 5 or 10 minutes (or however long your expiry time is). Without a refresh token, now they’re logged out. That’s pretty bad UX.

And issuing a new JWT every 10 minutes certainly seems akin to “setting and constantly refreshing expiries on the session keys” which you called out as being a drawback of server-side sessions in a different post.


I'm aware of this trade-off. It's fine, even desirable, for high security applications.

For other scenarios with lower security requirements like social networks, games etc... you could set the expiry to 24 hours so if the user uses the app at least once every day, then they will stay logged in perpetually.

The lower your security requirements, the further you can set the expiry time. If your security requirements are low, then you probably don't need the ability to revoke a token in 10 minutes anyway. It works out quite well. You can always have an isBanned flag/property on the user's account object for banning. So inside your access control logic, you check for the JWT and also check that isBanned is not true on the account record... OK, that means you need to look up the account record (which you would have to do anyway regardless of what session mechanism you use because it doesn't make sense to store an isBanned flag on a session object, but you really need that flag) JWT still saves you from managing session objects in a separate Redis instance or other.

If you compare the work and complexity involved in developing and maintaining the two solutions side-to-side, JWT is still much simpler overall for pretty much all scenarios. If you're talking about scenarios at scale, then JWT comes out even further in front. Session IDs require an entire extra infrastructure component; e.g. Redis.


> If you compare the work and complexity involved in developing and maintaining the two solutions side-to-side, JWT is still much simpler overall for pretty much all scenarios.

I still disagree, especially given the prevalence of session based solutions in pretty much every web framework out there.

Your post contains a couple of suggestions that are counter to just about every piece of advice I’ve ever read about JWTs (for example, increasing expiration times to a day). So, consider me thoroughly unconvinced.

And you’re not even considering the solution that some web frameworks (e.g. Rails) ship by default, which is to store the entire session object itself in a cookie, which was purpose built for that sort of thing. Then very little is required on the server.


In the rails example you gave, if they go so far as storing the entire session object in a cookie, I don't see why they wouldn't just use JWT as it's basically the same idea with an added signature to prove that it was generated by the server. Why would you invent something new which is just about as complex, has the same disadvantages and has fewer advantages?


Because the mechanism used is is simple and sufficient, and using JWTs would be more complex. Rails encrypts the cookie data so signatures are unnecessary.

Also, Rails has been doing this since 2007, three full years before the JWT spec was first published.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: