Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it more efficient to store the permissions of the user in an JWT claim or to check it on the server at every request?

JWT is an great way to make sure the data send to the user and back is not tampered with, but that makes for some tough choices. At the moment I am in the dilemma of choosing between storing the authorization data in an JWT claim and only touch the database once for the authorization, or just store the user ID and check the authorization levels on each request to the server with the database.

What makes this such a hard choice is that the application works with multiple authorization levels which makes the base64 encoded url quite long and bulky (see below what can be expected to be stored as authorization levels).

On the other hand, to get the authorization, two lookups in the database are necessary.

So my question is as following; Is the extra overhead on each request by sending the permissions to the server worth avoiding the hassle of looking up the permissions upon each request?

As an sidenote; In the case of permission changes the look-up-in-the-database approach has the benefit of not requiring the user to log in again (see post).

"perms": {     "roles": [         {             "name": "Admin",             "id": 1,             "assigned": true         },         {             "name": "Webmaster",             "id": 8,             "assigned": true         }     ],     "actions": [         {             "id": 1,             "name": "cms-edit",             "parameters": null,             "parameterized": null         },         {             "id": 9,             "name": "admin-syslog",             "parameters": null,             "parameterized": null         },         {             "id": 10,             "name": "admin-debug",             "parameters": null,             "parameterized": null         },         {             "id": 12,             "name": "member-list-extended",             "parameters": null,             "parameterized": null         },         {             "id": 2,             "name": "cms-list",             "parameters": null,             "parameterized": null         },         {             "id": 3,             "name": "cms-add",             "parameters": null,             "parameterized": null         },         {             "id": 5,             "name": "member-list",             "parameters": null,             "parameterized": null         },         {             "id": 7,             "name": "member-view",             "parameters": null,             "parameterized": null         },         {             "id": 8,             "name": "member-edit",             "parameters": null,             "parameterized": null         }     ] 
like image 629
Tom Stock Avatar asked Jul 24 '18 21:07

Tom Stock


People also ask

What is the best way to store JWT in client?

Use cookies to store JWT tokens – always secure, always httpOnly, and with the proper same site flag. This configuration will secure your client's data, it will prevent XSS and CSRF attack and also should simplify web application, because you do not have to care about using tokens manually on frontend code anymore.

What is the best place to store JWT?

To keep them secure, you should always store JWTs inside an httpOnly cookie. This is a special kind of cookie that's only sent in HTTP requests to the server. It's never accessible (both for reading or writing) from JavaScript running in the browser.

What do you store in a JWT claim?

jwt Getting started with jwt What to store in a JWTRegistered claims like sub , iss , exp or nbf. Public claims with public names or names registered by IANA which contain values that should be unique like email , address or phone_number . See full list. Private claims to use in your own context and values can ...

Should I store JWT username?

In a general case you would not need to keep user credentials in the JWT because the JWT is by itself a dynamically generated credential that represents the login / password provided at the JWT's first generation time.


2 Answers

Depends on how you interpretate efficiency. When speaking about resource efficiency, keep in mind that your JWT is transmitted on every request. So if you have a large application with fine grained access control lists (ACLs) and you always ping-pong these lists back and forth on every request-response then this will definitely cost you a few kilobytes depending on the number of requests you issue.

like image 44
B12Toaster Avatar answered Sep 22 '22 12:09

B12Toaster


Your first question:

Is the extra overhead on each request by sending the permissions to the server worth avoiding the hassle of looking up the permissions upon each request?

Answer:

Let's have a look at the description jwt.io provides on when to use JWTs:

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 means that you need to generate the token on the server side once the user logs in.

It contains:

  • The user (as an id or name)
  • The roles the client has (user, admin, guest, whatsoever...)

Once the client requests or sends data to the server, the server checks first, if the given token is valid and known and then it would check if the roles meet the criteria for accessing a certain resource.

All of the role/access data can be read once at system startup and kept in-memory. Moreover, the roles that a client has are only read once from the database as the client logs in. That way you have no subsequent database accesses and thus, a great performance increase.

On the other hand, if the client requests data or wants to perform an action, you need an authentication mechanism that evaluates if the token that was passed got the roles that are required in order to do so.

That way we solved the database hassle, plus we eliminated the danger of exposing too much information to the client (Even the client can't tamper the data, it can read the data!)

Note on that: https://jwt.io/introduction

Do note that with signed tokens, all the information contained within the token is exposed to users or other parties, even though they are unable to change it. This means you should not put secret information within the token.

See A3 (Sensitive Data Exposure): https://www.owasp.org/index.php/Top_10-2017_Top_10

Finally: Do also invalidate the tokens if the client is idle too long or logs out on purpose.

Follow-up question:

The case of permission changes the look-up-in-the-database approach has the benefit of not requiring the user to log in again

Answer:

Depending on your server's infrastructure you can either write a refresh mechanism (if the role updates, the server generates a new token and sends it to the client along with the answer generated, invalidating the old, the client uses only the recent token and overrides the old) or add some state, like a client session, on server side:

Eliminate the roles/permissions at the token. You are better with generating a session for the client and feed the session roles/permissions on the server side. The client gets the session token (usually an id) it can authenticate with. Once a permission/role change we have to do two things:

  1. Update the database
  2. Update the roles/permissions of the session

Again, every subsequent request will do the role/permission check in-memory and needs no database communication, while the client has only a small session token (or your JWT). Thus, role/permission changes are transparent to the client (no relog is required) and we eliminated the JWT refresh requirement.

like image 67
Akar Avatar answered Sep 19 '22 12:09

Akar