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

Where I've seen this turn into an argument is when people disagree about whether authorization info is "sensitive." Is it okay to send a list of roles or other authorization info in an unencrypted JWT? Security-wise this seems like it adds risk, but people often argue that it's a good trade-off in order to avoid a round-trip to an auth server (probably with a caching layer in front) for every call.


I figure unencrypted should be useful to the frontend, but use encrypted for authentication or authorization.

Unencrypted: maybe a user preference, or first name, or something that adds value but does not overlap with auth. Like if a frontend could serve the same functionality across three departments but the styling is different, the token's unencrypted claims could determine which style set to use.

Encrypted: user uuid, roles, maybe other known settings, things the backend can handle. Someone stealing a token will just try it anyway whether they can see claim or not, but because it's encrypted it will get decrypted so it's also a different logic flow than unencrypted and could trigger a process i.e. did it come from an accepted ip address or range? Does the ip match the previous? Does the ip match the other known ip for a websocket? So also in this sense we wouldn't want anyone to know what else we might check.


The front end almost always needs to know what a user is authorized to do, because it is reflected in the UI. Which edit/delete buttons are visible and active? Is there a link to the admin page? Is there a link to a supervisor dashboard? Most apps send that information to the front end in a way that maps 1-to-1 to how they model authorization on the back end, often using exactly the same language, in which case you don't gain much by encrypting it in the JWT. But if you are taking measures not to leak your authorization model in the front end, then it makes sense not to expose it in an unencrypted JWT.


> But if you are taking measures not to leak your authorization model in the front end

How would you do that? At the end of the day the front-end needs to know what you can access somehow.

I guess you could add a compile step that rewrites all your permission checks into validating opaque uuid’s.


Say you steal the token, what are you going to do with it? You could argue that you can now iterate all the tokens you steal, decode all of them, and find the ones with admin permissions. But if you have a frontend that wishes to know user permissions/access, you already have an endpoint for that too, so they can call that with all the tokens instead.

The thing is that you cannot change the payload of the token without invalidating it, so you couldn’t set the role to admin and then still have the server accept it.


There's no concrete exploit that it enables, but in principle it's always a risk to leak information about your security implementation. My opinion is that it's a very low risk for almost everybody, worth trading away for extra reliability and scalability if you need it.

To answer the question in your other comment, the back end can, in principle, provide a boolean yes/no value for every authorization-related decision the front end needs to make: can_change_order_status, can_view_supervisor_dashboard, can_view_all_conversations, etc. That way you never leak the model (such as roles) underlying those decisions. In practice, I've never seen anybody bother. Instead they have the back end send the front end values that map 1:1 to the back end authorization model: is_supervisor, is_account_admin, etc. That's why I think for most applications it doesn't matter if users roles are encrypted in the JWT.


And then most people hit the db anyways, since they use the jwt as a session cookie anyways.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

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

Search: