| As a side question (or rather, what I expected the central point of the article to be instead): how are you supposed to actually use JWT? The point of JWT vs opaque tokens is that you can just inspect the token itself to derive permissions without hitting any sessions in DB, right? This means we need a short-lived access token (5 min or so?) so that sessions are revoked in a reasonable time if the token is stolen somehow (this is already scary to me TBH, someone can still do horrific things in 5 mins of intrusion time, but that's another story). Now my question is... how do you even handle the refresh token then? I understand that long-lived refresh tokens means you can actually go to the DB/microservice/whatever and check if the refresh token has been revoked (via log out for example) since they'll valid for much larger intervals, so you can afford the session lookup... But if a refresh token is long-lived, what is the difference from having an actual long-lived access token? You'll still be handing out access token for a while. I can't see the difference here. What am I missing? EDIT: I could see the point if the threat models for both were different (e.g. having access tokens in memory, refresh tokens in a super safe vault, like e.g. ChatGPT would need to do for actions) but having both refresh+access tokens in the same threat model seems like it does nothing to me. |
Those downstream services can then perform all their authorisation checks using just the JWTs alone. They don’t need to reach out to the authentication service to validate them, or lookup permissions, that’s already happened upstream. If those downstream services need to call other services, they can just pass along the JWT, and it allows the next service to validate the request is performing an allowed operation, without having to contact the auth service, or perform user lookups etc to determine what’s a valid operation. It’s all encoded in the passed along JWT.
There’s also security advantages because the issuing and primary validation of JWTs can be isolated to a single well vetted service, that has very limited connectivity, and every other service uses JWT validation with public keys to perform permission checking, rather than endless user auth lookups. Those service would also have to contact your central auth service to get new JWTs issued, ensuring there’s only a single place in your infrastructure that holds the sensitive private signing keys, and has the ability to issue new tokens. Which means you have a single gatekeeper that determines what types of tokens other services can access, allowing you to enforce limits on those services, even if they don’t cooperate (maybe they’re owned by a different team). It also provides a central location to limiting the blast radius of compromises, you can mass invalidate tokens with cooperation from other services, and stop issuing new tokens to services that might be compromised.
Ultimately JWTs shouldn’t be used for “efficiency” or “performance”, but rather as a tool that allows you segregate sensitive authentication and authorisation infrastructure from all your other services, and prevent “normal” services from adding ad-hoc authentication and authorisation capabilities in way that’s hard to audit or control, without limiting their ability to enforce authorisation requirements.