Introduction to JWT Authentication

Introduction to JWT Authentication

what it is, how it works, and how to implement it in your project

Introduction

Hey folks, in this blog I am going to talk about what JSON Web Token(JWT) is, how it works and how you can implement it in your project. I will try to keep it simple and concise, so let's get started.

What is JWT

JSON web token(JWT) is basically a self-contained way for securely sharing information between two parties. This information can be trusted as it is digitally signed. JWT tokens are signed using different algorithms like HMAC, RSA, etc which is defined in the header part of JWT(discussed below)

A typical JWT looks like xxxx.yyyy.zzzz and is made of 3 parts separated by dots:

1.Header

The header typically consists of two parts: the type of the token, which in our case is JWT, and the signing algorithm being used, such as HMAC SHA256 or RSA For example

{
  "alg": "HS256",
  "typ": "JWT"
}

Here the header is working on the HS256 signing algorithm and the type of the token is JWT

2.Payload

The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional data. A typical payload looks like this

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

Note: You should never put private data in header or payload unless it is encrypted.

Note: All 3 parts of JWT are Base64Url encoded.

3.Signature

Signature is the main secret part of JWT. To create the signature part you have to take the encoded header, the encoded payload, a secret (we will come to this later in the implementation part), the algorithm specified in the header, and sign that. Signature is what verifies that the sender of the JWT is who it says it is.

So finally we have a 3 part JWT made of 3 Base64Url encoded strings separated by dots.

How JWT works

Let me explain this with an example, and for that let's go to an amusement park. Now to enter the park you have to buy a ticket. For our particular case let's assume no person can use another person's ticket to enter the park. Based on the decision of buying a ticket three cases occur:

  1. You don't buy a ticket and try to enter the park without a ticket.
  2. You try to enter the park by using your friend's ticket.
  3. You had come to the same park yesterday, and you are trying to enter the park by using yesterday's ticket.

Now let's consider the ticket as our JWT and the park as our protected application and understand how JWT works:

Case 1:Request to the application without token

So you went to security without any ticket, and for obvious reasons, you won't be allowed to enter.

Similarly, when a request without a JWT is sent to the app, it is not authenticated, and the request is rejected.

Case 2: Request to the application with the wrong token

You ask your friend to give you his ticket so that you could enter, but when you reach security you are not allowed to enter as it does not have your details.

Similarly, any request to the application having any token other than the assigned one will be rejected upfront.

Case 3: Using assigned token after it has expired

You reach your pocket and see that you have a ticket to park but it is from yesterday, you reach out to security but sadly you are not allowed as the ticket was valid for yesterday only.

Similarly, if a request is sent to the application with a token that has expired(more about this later), the request will be rejected.

Implement JWT in your project

Let's see how we can implement JWT in our project in the last part of our article

first off we need to add a package

$ npm install jsonwebtoken

after the package is successfully installed, import it into your app

const jwt = require("jsonwebtoken");

to make a token, there are some options, and to make and sign a token that expires after a given time period, do

const token = jwt.sign({ userId }, secret, {expiresIn: "24h"});

the above process uses the HMAC SHA256 algorithm to sign the token

let's breakdown the above code

jwt.sign(): is a function that signs a token using a particular signing algorithm, it takes 2 necessary arguments: payload which is userId here in our case, a secret which can be any string, and an optional argument for token expiration.

The secret should optimally be many characters long for security purposes. Personally, I have been using the crypto module of the nodejs to create a strong enough secret:

node -e "console.log(require('crypto').randomBytes(256).toString('base64'));"

this will create a random and strong enough secret to be used for making JWT token Note: Never keep the secret visible in code anywhere or push it to Github. Keep it in .env file and keep .env in .gitignore

Token Verification

Now the token is ready and we can send it to the request initiator(eg when a user logs in), and every time the said user comes back with any other request its token will be checked and verified, if matched then it will be allowed to make the said request as we discussed in the example of the amusement park early on. The verification is usually done in a middleware which is accessed before each request proceeds to the actual endpoint

 const decoded = jwt.verify(token, secret);

The token is coming with the user's request and the secret is which we have used during the signing of the token.

verify() matches the token and secret and returns the payload decoded if the signature is valid and optional expiration, audience, or issuer are valid. If not, it will throw the error.

 try {
    const decoded = jwt.verify(token, secret);
    //Case 1: token is verified,authenticate and  continue with the request 

  } catch (error) {
  //case 2: token not verified, don't authenticate and send 401 resposne 
}

Two cases arise after verify() does is execution

Token is verified: then the request is allowed to proceed to the particular endpoint

Token is not verified:if the token is expired or tampered with, an error will be thrown as the token won't match with the secret. We can send a 401 response to the front-end ie an unauthorized request.

How to handle 401 response in front-end, an idea:

In the front-end what we can do is that we can write an Axios interceptor which will check for every response after the request comes back. If the token is verified, the response is good to go, but if the token is not verified Axios interceptor should catch the unauthorized error, log out the user, and take him to the login page, where the user can log in again and a new token will be assigned to him in the process. I won't go deep into this as it is beyond the scope of this article, but if you guys want me to write about how to intercept the 401 responses in the front-end with the help of Axios interceptors, let me know in the comments, I will surely work on it.

So that's it from this article, If you have reached till here, thank you for reading, and I hope that you have understood now what JWT is all about if not before. If you have any questions, feel free to shoot them down in the comments. Actually this is my first ever blog post, so any kind of feedback or suggestion will be highly appreciated.

Until next time, Adios!