Is setting Roles in JWT a best practice?

ayorosmage picture ayorosmage · Nov 10, 2017 · Viewed 27.1k times · Source

I am considering to use JWT. In the jwt.io example I am seeing the following information in the payload data:

"admin": true

Admin can be considered as a Role, hence my question. Is setting the role in the token payload a habitual/good practice? Given that roles can be dynamically modified, I'm quite interrogative.

Answer

B12Toaster picture B12Toaster · Nov 28, 2018

The official JWT site explicitly mentions "authorization" (in contrast to "authentication") as a usecase for JWTs:

When should you use JSON Web Tokens? Authorization: This is the most common scenario for using JWT. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token. Single Sign On is a feature that widely uses JWT nowadays, because of its small overhead and its ability to be easily used across different domains.

That being said, from a security-perspective you should think twice whether you really want to include roles or permissions in the token.

(The text below can be understood as a more "in-depth" follow up to the rather short-kept accepted answer)

Once you created and signed the token you grant the permission until the token expires. But what if you granted admin permissions by accident? Until the token expires, somebody is now operating on your site with permissions that were assigned by mistake.

Some people might argue that the token is short-lived, but this is not a strong argument given the amount of harm a person can do in short time. Some other people advocate to maintain a separate blacklist database table for tokens, which solves the problem of invalidating tokens, but adds some kind of session-state tracking to the backend, because you now need to keep track of all current sessions that are out there – so you would then have to make a db-call to the blacklist every time a request arrives to make sure it is not blacklisted yet. One may argue that this defeats the purpose of "putting the roles into the JWT to avoid an extra db-call" in the first place, since you just traded the extra "roles db-call" for an extra "blacklist db-call".

So instead of adding authorization claims to the token, you could keep information about user roles and permissions in your auth-server's db over which you have full control at any time (e.g. to revoke a certain permission for a user). If a request arrives, you fetch the current roles from the auth-server (or wherever you store your permissions).

By the way, if you have a look at the list of public claims registered by the IANA, you will see that these claims evolve around authentication and are not dealing with what the user is allowed to do (authorization).

So in summary you can...

  • add roles to your JWT if (a) convenience is important to you and (b) you want to avoid extra database calls to fetch permissions and (c) do not care about small time windows in which a person has rights assigned he shouldn't have and (d) you do not care about the (slight) increase in the JWT's payload resulting from adding the permissions.

  • add roles to your JWT and use a blacklist if (a) you want to prevent any time windows in which a person has rights assigned he shouldn't have and (b) accept that this comes at the cost of making a request to a blacklist for every incoming request and (c) you do not care about the (slight) increase in the JWT's payload resulting from adding the permissions.

  • not add roles to your JWT and fetch them on demand if (a) you want to prevent any time windows in which a person has rights assigned he shouldn't have or (b) avoid the overhead of a blacklist or (c) avoid increasing the size of your JWT payload to increase slightly and (d) if you accept that this comes at the cost of sometimes/always querying the roles on incoming requests.