In the previous blog, we saw why we need to shift to token based authentication, instead of the traditional authentication process and also we went into what is a JSON Web token. Now let us see in detail what JSON Web Token is and how it can be used for user authentication.
As we have seen earlier JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.
JSON Web Tokens consist of three parts containing encoded data, separated by dots (.), which are:
Therefore, a JWT typically looks like the following.
The header typically consists of the type of the token, which is always JWT, and the hashing algorithm being used, such as HMAC SHA256 or RSA.
when this is base64encoded, we have the first part of our JSON web token
The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional metadata. There are three types of claims: reserved, public, and private claims.
JSON Web Token defines some reserved claim names and defines how they should be used. JWT supports these reserved claim names:
- ‘exp’ (Expiration Time) Claim
- It specifies the time till which the token is valid.
- ‘nbf’ (Not Before Time) Claim
The nbf (not before) claim indicates the time before which the JWT MUST NOT be accepted for processing.
- ‘iss’ (Issuer) Claim
The iss (issuer) claim identifies the principal that issued the JWT. The processing of this claim is generally application specific.
iss = Mallow Technologies Pvt Ltd. or https://mallow-tech.com
- ‘aud’ (Audience) Claim
The aud (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the aud claim when this claim is present, then the JWT MUST be rejected.
- ‘jti’ (JWT ID) Claim
The jti (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issues, collisions MUST be prevented among values produced by different issuers as well. The jti claim can be used to prevent the JWT from being replayed. The jti value is a case-sensitive string.
- ‘iat’ (Issued At) Claim
The iat (issued at) claim identifies the time at which the JWT was issued. This claim can be used to determine the age of the JWT. Its value MUST be a number containing a Numeric Date value. Use of this claim is optional.
These can be defined at will by those using JWTs. But to avoid collisions they should be defined in the IANA JSON Web Token Registry or be defined as a URI that contains a collision resistant namespace.
These are the custom claims created to share information between parties that agree on using them.
To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.
For example, if you want to use the HMAC SHA256 algorithm, the signature will be created in the following way:
HMACSHA256( base64UrlEncode(header) + “.” +base64UrlEncode(payload),secret)
How can JSON Web Tokens can be used for User Authentication?
- It is a stateless authentication mechanism where user’s state is never saved in the memory. The server will check for a valid JWT in the Authorization header, and if it’s present, the user will be allowed to access protected resources. As JWTs contains all the necessary information within itself, reducing the need to query the database multiple times.
How JWT Works
- User successfully logs in using his credentials.
- The server responds with a JSON Web Token, this token contains the details of the user which is used to be used by server often, it may be the user_id, username, email etc. The expiry time of the token must be configured using the exp claim. All these details are encoded based on some algorithm such as HMAC SHA256 or RSA.
- The token provided to the client must be saved locally and sent in the headers of each request.
- Server decodes the token and verifies the token is valid or not. If valid then it allows the user to access the restricted resource.
- When a JWT gets expired we need to refresh the token or we need to create a new token and allow the client to access the resources otherwise the user will have to sign in to the application frequently this will irritate the user. So a refresh token mechanism can be adopted.
- In addition to a JWT server will respond the client an additional token called refresh token which will have much higher expiry time when compared with JWT access token.
- When an access token gets expired client will send the refresh token to server verifies the refresh token and provides the new access token.
Advantages of using JWT
- Since you have all details in the token itself server need not query about the details of the user from DB.
- As server don’t use any sessions for storing the details of the user, memory consumption is decreased and server can also be scaled up based on the traffic.
- Any client having a valid JWT can access the resource so this can also be used by mobile devices for consuming APIs.
- By setting the expiry time to a token, even if a token being misused it can’t be used for a long time as the token will expire will at a certain time.
Disadvantages of using JWT
Though JWT is advantageous in many ways it still has some limitation too,
- Token provided to the user after successful authentication will be valid even if the user logs out from the system.
- When the expiry time of a token is set to small time, then these token will get invalid within a little amount of time. But for an application where we need higher security, this small amount of time does play a vital role.
Invalidating JSON Web Tokens
As mentioned earlier a valid JSON Web Token of a logged out user can also be used for accessing the restricted resources. If you are building an application where you need high security you need to make sure this doesn’t happen. In order to implement a user authentication system for such kind of application, you need to compromise with some advantages of JWT. In such cases, you need to keep track of the token which is invalid/valid.
A JWT will get expired based on the exp claim in the payload, after which the token cannot be used. There are also some scenarios in which the tokens must be invalidated before its expiry, those are
- When a user logs out from the application before the token gets expired.
- When the user resets the password.
This can be handled by two ways
In this process tokens which are not valid are stored in the DB. We need to handle the following situations,
When the user changes his password note the change password time in the user DB, so when the change password time is greater than the token creation time, then the token is not valid. Hence the remaining session will get logged out soon. “iat” claim can be used for getting the token creation time.
When User logs out, save the token in a separate DB (say: Invalid Token and remove the token from DB when token expires). Hence user logs out from the respective device, his sessions in other device left undisturbed.
In this process tokens which are valid are stored in the DB and remove the tokens which get expired. You need to handle the following situations
When User changes his password, delete all the tokens of the tokens, as these tokens become invalid.
When User logs out, delete that particular token from the DB, as a single user may log in multiple devices, so delete a particular token.
As said earlier we have some limitations in JWT too. The process of invalidating the JWT is an optional one, this can be implemented when you think that the resources are more secure and it should not be at any point in time. If you think that the data of the application can be accessed by the user using the token which will expire within a shorter duration then this process can be skipped, as it leads to compromise with a stateless property of JWT.