86

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.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
ayorosmage
  • 1,607
  • 1
  • 15
  • 21

4 Answers4

146

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 size 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 size 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.

hashlash
  • 897
  • 8
  • 19
Felix K.
  • 14,171
  • 9
  • 58
  • 72
  • 41
    If you are to mistakenly grant an admin permission to a user, and if he or she is willing and able to do significant damage in a really short period of time, then you are likely going to pay a very steep price for your mistake regardless of your authorization implementation. No web security protocol can guard against a threat of that nature. – Nate T Feb 20 '20 at 17:19
  • @NathanToulbert Agree 100% . User mistakes and bad practises (while using an app ) are the most weak part of every application.. – skechav Oct 25 '20 at 22:59
  • 3
    Want to add a comment about the 2nd approach. Implement a bloom filter to create a blacklist could save a lot of calls to db, so this might improve the cost making a request for every incoming request. – Kaihua Dec 06 '20 at 21:44
  • @NateT this is a completely valid comment but it also relates to the talent on your team. There certainly are benefits of using role based tokens when you take performance into account. But I also would not let my JR developers loose on a task that important. – Husk Rekoms Sep 16 '21 at 19:57
  • 1
    The exmaple given could be improved. What if a user is granted a token, then before the token expires the user is fired from the job? This might be a more legit reason for prematurely revoking tokens other than huamn error. – Lionet Chen Feb 09 '22 at 05:14
82

Nothing stops you from creating claims to store extra information in your token if they can be useful for your client.

However I would rely on JWT only for authentication (who the caller is). If you need to perform authorization (what the caller can do), look up the caller roles/permissions from your persistent storage to get the most updated value.

For short-lived tokens (for example, when propagating authentication and authorization in a microservices cluster), I find it useful to have the roles in the token.

cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • 23
    the down side of this is that the app has to know this info. In many environments the app has no other access to information about the user apart from claims in the token . So it depends on the exact use case. But yes, it is perfectly normal to add role info to a JWT – pm100 Nov 10 '17 at 16:14
  • 3
    Thought the 2 words _authentication_ and _authorization_ are the same and used interchangeably. Thanks for the info :) – Ziad Akiki Dec 01 '19 at 11:07
  • 4
    Authentication is basically the practice of making sure that the user is who they say they are, and authorization is the process of making sure that the user has permission to access a destination. – Nate T Feb 20 '20 at 17:01
  • Modern standards like OIDC and central identity systems make use of JWT claims, for full central control over access. Then systems only need to be mapped to the claim. The token from an OIDC can also be used to generate an application specific one. – Kind Contributor Sep 21 '20 at 07:29
  • Maybe it is better idea to have separate Jwt Token for other roles – Ernest Rutherford Dec 07 '22 at 12:48
42

As mentioned here, ASP.NET Core will automatically detect any roles mentioned in the JWT:

{
  "iss": "http://www.jerriepelser.com",
  "aud": "blog-readers",
  "sub": "123456",
  "exp": 1499863217,
  "roles": ["Admin", "SuperUser"]
}

and 'map' them to ASP.NET Roles which are commonly used to secure certain parts of your application.

[Authorize(Roles = "Admin")]
public class SettingsController : Controller

The server which is giving out (and signing) the JWT is commonly called an authorization server and not just an authentication server, so it makes sense to include role information (or scope) in the JWT, even though they're not registered claims.

Community
  • 1
  • 1
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
  • Of course you still have to put them in there somehow ;-) This question seems to be a popular way of doing just that - https://stackoverflow.com/a/42037615/16940 - especially if you're in .NET land and need to create a token with ASPNET roles or role claims. – Simon_Weaver Jun 14 '19 at 09:24
  • Not to mention that the token is passed as the value of the "authorization" key in the header. – Nate T Feb 20 '20 at 17:22
-2

JWT tokens are designed to be tamper-proof.

if a JWT token includes a "role" claim indicating that the user has a certain role or permission, the client cannot modify that claim to give themselves additional permissions.

(in case he did) Attempts to modify the token could be detected and rejected by the server, or could simply result in the client being denied access to the requested resource.

example in my case I'm using API-Platform and it can check for modified tokens by validating the signature of the token and verifying its contents against the server's records. If any modifications are detected, the server will reject the request and the client will not be granted access to the requested resource.

Vlad
  • 11
  • 1
  • 5