Remix.run Logo
himata4113 4 hours ago

Hmh, 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 4 hours ago | parent [-]

irrevocable* cache

himata4113 4 hours ago | parent [-]

I'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.

encodedrose 30 minutes ago | parent [-]

This is an interesting approach especially if you factor in that re-minting a key is usually a lightweight task compared to what most API calls have to interact with.

If the re-minting happens transparently with a user interaction then you spread out some of the request velocity that can come with that (if you're operating at a large enough scale for it to matter for this to be a concern).