Authentication using JWT - Advantages, Disadvantages and Structure explained.

Authentication using JWT - Advantages, Disadvantages and Structure explained.

In this blog I will be talking about authentication using JSON Web Tokens. I will be covering the structure of a JWT, along with some advantages and disadvantages of using JWTs.

Why simple Authentication doesn't work

Dynamic websites such as blog websites, chat apps need to know who the user is in order to display their respective chats, blogs etc. accordingly. In order to verify the user's identity, authentication is implemented in these projects. Authentication can be in the form of a login form or in the form of third party oauth such as google, facebook, github etc. Authentication is neccessary to manage user permissions. After the user is authenticated, he can access features such as sending messages, creating a blog etc. based on the permissions he has and can access his received messages as well.

The HTTP protocol is stateless ie., it does not keep track of previous requests made to the same server. In order to keep track of the current user, the website would have to authenticate the user everytime he wishes to access a new page. However, we typically observe that websites don't make us login for every new page, instead they make us login once and we are able to access all the features we have permission to access.

In order to achieve this, servers would need a way to remember the current user after he/she logs in. This can be achieved by storing some data about the current user on the server or on the client side. Two popular methods to store the data are:

  • Sessions

  • JWT (Json Web Tokens)

Session based authentication

When the user is authenticated, the server creates a unique session id and associates that session id with user information. The user information is stored directly on the server in server memory (can be stored in a cache as well). This session id is stored on the client side (in a cookie) and is sent to the backend with every request. The server can use the session id to find the current user.

Drawbacks of Sessions

  • When multiple copies of the same server exist : Let's say server 1 created the session for the user, only server 2 would be able to remember the user in case he accesses other endpoints. However if the load balancer directs the user to server 2 in his next request, this would be a problem since server 2 does not remember the user and he would need to be authenticated again.

Ways to solve these problems

  • One way would be to make sure the load balancer always redirects a single user to the same server everytime, this would ensure that the server remembers the user and authorization is properly implemented.

  • Using a shared data storage can fix this problem. Instead of storing the data directly on the server, we can use a shared data store where all different servers would store session data. This is a good use case for a cache since it is the fastest and most suited for this case. The session id can be mapped to user data in a key value store. In this case it wouldn't matter which server the user is redirected to since the data actually lies on a shared cache. However this brings problems of its own. Caches are expensive and when the number of users grows you would typically want to avoid storing data for multiple users on a cache.

  • Using JWTs can help resolve this issue. JWTs do not store data on the server side, instead they store key user information on the client side itself. Instead of sending a session id to the server, we can send key user data directly. This would eliminate the problem of shared servers since the server is receiving user data needed to authenticate the user with the request.

JWT based authentication

Server creates a JWT with necessary user info as payload. This JWT can be stored in cookie or local storage on the frontend and then is sent to the server with every request as an Http header(Authorization bearer). This approach prevents the server from storing user data in memory and hence is scalable.

Drawbacks of JWT

  • Sessions are extremely easy to delete, however JWTs contain user data in the payload hence simply deleting them from the cookie or local storage would not delete the JWT. The token can still be used by attackers to gain unauthorized access.

  • To manage this, devs need to implement a mechanism for tokens to be invalidated after a fixed amount of time. Compromised tokens also need to be invalidated through blacklisting etc. Refresh tokens also need to be implemented which adds an additional layer of complexity.

JWT structure

A JWT consists of three main components:

  • Header : Consists of the hashing algorithm and the token type.

  • Payload : Consists of the actual data used for auth.

  • Signature : Consists of the signature which helps avoid tampering of data and maintain integrity of payload.

(Source : https://jwt.io/.)

Header

As visible in the image above, the header consists of the name of the algorithm used for signature (in this case it is HS256) and the token type which is JWT in this case.

There are multiple algorithms which can be used for performing signatures.

Payload

The payload needs to contain data such as the user id, the username, phone number etc. The payload should NOT contain the password as JWTs are publicly visible hence any form of sensitive information should not be stored on a JWT. Also the payload should not contain too much unnecessary data since the data is stored on the client side and should not be too bloated.

Signature

At the time of JWT creation, a signature is necessary to ensure that malicious users do not change the payload. Changing the payload can enable users to access other accounts through the JWT. Hence the signature is necessary to ensure payload integrity.

Maintaining payload integrity in JWT

JWT signatures are a hash, hashes depend on two things - the data being hashed (payload in this case) and the key. If either of the two changes , the signature will change. Since the secret key is fixed by the developer, this makes sure the user cannot change his payload data to someone else's data. If he does, the signature would change and the server would be able to identify the tampering due to change in the signature. The signature hence maintains payload integrity.

Here is a small example of how the signature changes when the payload is changed:

The signature is in blue (on the left half), for the same key watch how it changes when I change the name from John Doe to Aditya Bisht.

Hence the signature can easily be checked to see if payload is the original signed payload.

I hope you learnt something from this blog, if you did, do drop a like and follow me on hashnode for future content.

Thank you for reading !!!