JWT - JSON Web Token

·

5 min read

You have seen these gibberish numbers in the URL section of web browser but what do these numbers represent?

JWT

It prevents the exposure of data through urls to potential hackers or general users while client-server communication.

JWT - JSON Web Token. For sake of simplicity, they are complex long strings that send the information over the web with added security feature due to the encoding.

Setting up router

const express = require('express');
const router = express.Router();

const {controller_one} = require('../controller-one')

router.route('/controller_one').get(controller_one);

Logic for creating a JWT -

check username and password in post login request. If both exists correctly, we create a new JWT else we send some message to frontend

On server end only the request with JWT token can access the dashboard.

Till now we had all routes as public, if the user was requesting for the route that was existing, we gave the response.

But now the frontend will interact with the backend using JWT, we will not show routes but only JWT. Mind it the frontend and backend should have the same tokens so that data can be exchanged. JWT has a security feature that ensures the integrity of our data, that's why it is better than any random string.

If the token passes the validation, it's the same token that we send to the client.

Remember HTTP is stateless so it does not remember the previous requests or responses sent by the same client this means frontend will have to provide a valid token else access to data will be denied.

JWT Structure

The resource is JWT.io We can read many things about JWT there. Here is the general structure of JWT -

1 . Header 2 . Payload 3 . Signature

The JWT typically looks like the following

xxxxxxxx.yyyyyyy.zzzzzzzzzz

Header

Header usually consists of two parts.

a . Type of token which is JWT b . Signing algorithm such as HMAC, SHA256 or 256

example :


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

Then this JSON is encoded with Base64Url.

Payload

Second part is Payload which is a term that we have heard before in the redux toolkit.

Payload is where we put the information. As a n example we can place the id of the user which is signed in, signed out etc. and then we send the entire token with that payload back to the frontend and the frontend sends it back to us and then we decode to extract the information.

We usually pass an object as payload. Make sure we don't pass a password or any other confidential data in payload

Payload contains the claims. Claims are statements about user(an entity) and additional data.

It is good if we keep the information sent over payload as small as it enhances the UX

The claims are of 3 kinds :

1 . Registered claims 2 . Private claims 3 . Public claims

Payload also gets encoded with Base64Url.

Signature

As per official docs, to create the signature part you need to the encoded header, the encoded payload, a secret algorithm specified in the header and sign that.

The secret will have to be kept on the server. In production make a complex unguessable string not a simple one.

jsonwebtoken package

One of the package to use JWT easily is jsonwebtoken and we will use the same in our project.

Start by importing it in our main.js file .


const jwt = require('jsonwebtoken');
const token = jwt.sign()

The sign() method it takes a payload, a secret key and options. Here is a sample


jwt.sign({id,username}, process.env.JWT_SECRET, {expiresIn:'30d'})

We are accessing the secret key from our .env file. Make sure to make it complex.

In the frontend we add 'authorization' in header which contains the Bearer and then token, this verifies the token exchanged between client and server side.

Send Bearer token using Postman

Consider we made a simple API which takes the username and password as requests for login and shows some data based on that on dashboard. So we have one route of login and other route for dashboard. Now, every time we send a successful request where the username and password are valid, we will get a token( we are sending the token on valid username and password only ).

Now in our postman, we are looking for Headers in our dashboard request. Remember we are looking for Headers and not Body. We will put the key as Authorization and value will be equal to the token we received back.

In bigger projects we will do it dynamically but for here we are just testing how we can send the Bearer from Postman.

A simple way to test the header has been provided correctly

const authHeader = req.headers.authorization

    if(!authHeader || !authHeader.startWith('Bearer')){
        throw new CustomAPIError('Please provide token', 401);
    }

Verifying token sent from frontend

One good practice is to put the verification code in try-catch block.

We are provided with .verify() method which takes the token we got from the frontend and secret string we have as our JWT string value.

try{
        const decoded = jwt.verify(token, process.env.JWT_SECRET);
        // rest code logic goes below this line

    }catch (err){
        throw new CustomAPIError('Not authorized to access this route', 401);
    }

Here we are throwing a custom error but you are free to put your own error here. If the token is incorrect, the code will throw an error.

That's all for understanding JWT. We can understand more about it as we keep building projects implementing it.