What is JWT

In short, JSON Web Token (JWT) is a securely encoded JSON object. This information can be verified and trusted because it is digitally signed. Because of its compact nature, JWT can be easily transferred in an HTTP header or through a URL, POST parameter.

You can use JSON Web Tokens for:

  • Authentication (most common case): when a user is logged in, each subsequent request contains a JWT thus allowing the user to access some secured application routes.
  • Exchange privacy data: JWT is a good way to transmit some information between parties. Tokens are signed using private/public keys so you can be sure a sender is the person you expect and not a fraud.

Token consists of three parts divided by ‘.’: “Header.Payload.Signature”. Header and Payload are Base64Url encoded.

Header is an object in JSON format with fields describing the type of token (always JWT) and the hashing algorithm (HMAC SHA256, RSA, etc.).

JSON

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

Payload is an object in JSON format with your payload, typically information about a user.

JSON

        {
  "name": "Dmitry Salnikov",
  "admin": true
}
      

Here is the JSON Web Token for the provided objects above: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJuYW1lIjoiRG1pdHJ5IFNhbG5pa292IiwiYWRtaW4iOnRydWV9. 2JpLJgOaSUIpuFCsu1MP3hw4FVqlyEXU9FkbqiLPOJ8

You can try to generate or decode your own token using jwt.io Debugger

JWT.io debugger helps to encode/decode JSON Web Tokens right in your browser

JWT.io debugger helps to encode/decode JSON Web Tokens right in your browser

by jwt.io

There are tens of JWT libraries written for all popular programming languages. You can read how to use it on their's Github pages. But in this article I’ll show you how to use Node.js jsonwebtoken library.

Libraries for work with JWT in different programming languages are listed on the JWT.io website

Libraries for work with JWT in different programming languages are listed on the JWT.io website

by jwt.io

Implementing login mechanism

First, install jsonwebtoken library:

Command Line

        npm install jsonwebtoken
      

All the code I provide is written in TypeScript. Here is the express router with a single ‘/login’ route:

JavaScript

        import { Router as expressRouter, Request, Response } from 'express';
import * as jwt from 'jsonwebtoken';

const router = expressRouter();

const ONE_DAY = 60 * 60 * 24;

function getToken(user: any): string {
  return jwt.sign({ name: user.name }, ‘secret’’, { expiresIn: ONE_DAY });
}

router.post('/login', (req: Request, res: Response) => {
  const name = req.body.name;
  const password = req.body.password;

  if (name === 'dmitry' && password === '1234') {
    return res.json({ token: getToken({ name }) });
  } else {
    return res.status(400).send('Wrong name or password!');
  }
});
      

I pass my JWT ‘secret’ to the server using dotenv library. Here for the sake of simplicity I hardcoded the value ‘secret’. I assume you are familiar with Express.js so there is no need to go too far into details.

You can query a user in your database using provided credentials and then if such user does exist - simply generate JWT token and send it back. In my code example, I used hardcoded user’s name and password instead of querying a database.

When you get a generated JSON Web Token you need to save it to localstorage to be able to use it when sending server requests.

How to send HTTP requests with JWT

Whenever the user wants to access a protected route or resource, the user agent should send the JWT, typically in the Authorization header using the Bearer schema. The content of the header should look like the following:

Authorization: Bearer

Here is how I send requests using Axios library:

JavaScript

        // here I get token from localstorage using my special service
const token = clientStorage.get(STORAGE_KEY.AUTH_TOKEN);

// send request passing authorization header
axios.post('/api/v1/protected-route', dataToSave, { headers: { Authorization: `Bearer ${token}` } });

      

Verifying tokens

Now when you can log into your system on the client you can prevent some components from rendering unless the JWT token exists and valid. To be sure that token is valid you need to send a request to your server to verify it. Here is how you could do that:

JavaScript

        import { Router as expressRouter, Request, Response } from 'express';
import * as jwt from 'jsonwebtoken';

const router = expressRouter();

function decodeToken(token:string) {
  let decodedPayload;
  try {
    decodedPayload = jwt.verify(token, process.env.JWT_SECRET);
  } catch(error) {
    decodedPayload = null;
  }

  return decodedPayload;
}

router.post('/validate', (req:Request, res:Response) => {
  const token = req.body.token;

  if (!token) {
    return res.status(400).send('You must provide a JWT token');
  }

  const tokenPayload:any = decodeToken(token);
  if (tokenPayload) {
    return res.json({ success: 'true', payload: tokenPayload });
  } else {
    return res.status(400).send('Invalid token');
  }
});
      

With ‘/validate’ endpoint you can detect if the token has expired or is a fake token, and based on the result you can prevent access to a malicious user to some parts of your client application. If you are using Angular you can use guards. You can read in details how to implement Angular guards in my article

Protecting API from unauthorized access

express-jwt library will help you to decode JWT from HTTP requests and protect your special routes and API endpoints. First, install the library:

Command Line

        npm install express-jwt
      

Now import it into your express router and use as a middleware. You can add another middleware to check for authorization error and send 401 status if there is one.

JavaScript

        import { Router as expressRouter, Request, Response } from 'express';
import * as jwtAuth from 'express-jwt';

const router = expressRouter();

const authorization = jwtAuth({ secret: process.env.JWT_SECRET });
const processAuthError = (error:Error, req:Request, res:Response, next:Function) => {
  if (error.name === 'UnauthorizedError') {
    res.status(401).send('Unauthorized access');
  } else {
    next();
  }
};

router.get(
    '/protected-route',
    [authorization, processAuthError],
    (req:Request, res:Response) => {
      // successfully passed authentication
      // req.user is your JWT payload object
      res.status(200).json(req.user);
    }
);
      

I hope this information helped you to better understand what is JWT and how easily you can use it to implement powerful applications.