top of page
Writer's pictureVansh Goyal

Understanding JSON Web Tokens (JWT): A Comprehensive Guide

JSON Web Tokens (JWT) have revolutionised modern web authentication and authorisation. This article provides an in-depth look at JWT, including its structure, implementation, benefits, and best practices.


Cover Page

What is JWT?


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. This information can be verified and trusted because it is digitally signed.


Key Features


  • Compact: JWTs can be sent through URL, POST parameter, or HTTP header

  • Self-contained: Contains all necessary information about the user

  • Digitally signed: Information can be verified and trusted


Structure of a JWT


A JWT consists of three parts separated by dots (`.`):

Example - eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlZhbnNoIEdveWFsIiwiaWF0IjoxNTE2MjM5MDIyfQ.GTU3sl-n9zc-tzQemgtO_34xFhUJ0g-Bfy0HGlLOssw


Header & payload

Here are three parts separated by two dots.

1. Header

2. Payload

3. Signature



Encoded & Decoded

Explained Everything Below:-


JWT Token Format
  1. Header


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

The header typically consists of two parts:


- The signing algorithm (e.g., HS256, RS256)

- The type of token (JWT)


  1. Payload

{
    "sub": "1234567890",
    "name": "John Doe",
    "admin": true,
    "it": 1516239022,
    "exp": 1516242622
  }

The payload contains the claims (statements about the user) and data. Common claims include:

- `sub` (subject)

- `iat` (issued at)

- `exp` (expiration time)

- Custom claims


  1. Signature


    The signature is created by:

    1. Taking the encoded header

    2. Taking the encoded payload

    3. Adding a secret

    4. Applying the algorithm specified in the header


Implementation Example


Backend Implementation (Node.js)

You can access this code on Git Hub here.


const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
// Secret key (store securely in production)
const SECRET_KEY = 'your-secret-key';
// Middleware to verify JWT
const authenticateToken = (req, res, next) => {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];
  if (!token) return res.sendStatus(401);
  jwt.verify(token, SECRET_KEY, (err, user) => {
    if (err) return res.sendStatus(403);
    req.user = user;
    next();
  });
};
// Login route - generates JWT
app.post('/login', (req, res) => {
  // Validate user credentials (simplified for example)
  const username = req.body.username;
 
  const user = {
    id: 1,
    username: username,
    role: 'user'
  };
// Generate JWT
  const token = jwt.sign(user, SECRET_KEY, { expiresIn: '1h' });
  res.json({ token });
});
// Protected route
app.get('/protected', authenticateToken, (req, res) => {
  res.json({ data: 'Protected data', user: req.user });
});

 Frontend Implementation (JavaScript)


// Making authenticated requests
const makeAuthenticatedRequest = async () => {
    const token = localStorage.getItem('jwt_token');
   
    try {
      const response = await fetch('http://api.example.com/protected', {
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json'
        }
      });
     
      const data = await response.json();
      return data;
    } catch (error) {
      console.error('Error:', error);
    }
  };

Benefits of Using JWT


1. Stateless Authentication

- No need to store session information on the server

- Reduces database queries

- Easier to scale horizontally


2. Cross-Domain/CORS

- Can be used across different domains

- Perfect for microservices architectures


3. Performance

- Lightweight

- Fast processing

- Reduced database lookups


4. Flexibility

- Can include any custom claims

- Works with various programming languages

- Supports different signing algorithms


Security Best Practices


1. Token Storage

- Store tokens securely (HttpOnly cookies preferred)

- Never store sensitive data in payload

- Use secure browser storage mechanisms


2. Token Configuration

const token = jwt.sign(payload, SECRET_KEY, {
    expiresIn: '1h',            // Short expiration time
    algorithm: 'HS256',         // Secure algorithm
    audience: 'your-app-name',  // Specific audience
issuer: 'your-company'      // Specific issuer
  });

3. Additional Security Measures

- Implement a token refresh mechanism

- Use HTTPS only

- Validate all inputs

- Implement rate-limiting


 Common Pitfalls and Solutions


1. Token Size

- Keep payload minimal

- Avoid storing unnecessary data


2. Token Revocation

Implement a token blacklist for critical situations:

const revokedTokens = new Set();
const checkIfTokenRevoked = (token) => {
  return revokedTokens.has(token);
};
// In your middleware
const authenticateToken = (req, res, next) => {
  const token = req.headers['authorization']?.split(' ')[1];
  if (checkIfTokenRevoked(token)) {
  return res.sendStatus(403);
  }
  // Continue with verification...
};

USE CASE


1. Single Sign-On (SSO) [Share authentication across multiple applications,Maintain consistent user experience]

2. API Authentication [Secure API endpoints, Manage user permissions]

3. Mobile Applications [Stateless authentication, Efficient token management]


Comparison with Other Authentication Methods


JWT vs Session-Based Authentication


Comparison

Output



Conclusion


JWT provides a scalable solution for creating a modern authentication system. It is far better than traditional or server-side session systems when implemented correctly with proper security measures. Its self-contained nature and flexibility make it particularly suitable for distributed systems and microservices architectures.

Get all the code on GitHub here.

When implementing JWT in your applications, remember to follow security best practices and the latest security recommendations.



147 views0 comments

Comments


bottom of page