Understanding JWT (JSON Web Token) and How It Works

JSON Web Token (JWT) is a compact, URL-safe method for securely transmitting information between parties as a JSON object. JWTs are commonly used for authentication and information exchange, ensuring integrity and authenticity.

What is JWT?

A JWT consists of three parts:

  1. Header
  2. Payload
  3. Signature

These are encoded in Base64Url and separated by dots (.):

xxxxx.yyyyy.zzzzz

1. Header

The header typically consists of two parts:

  1. alg – the signing algorithm (e.g., HS256)
  2. typ – the token type (JWT)

Example:

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

2. Payload

The payload contains the claims. Claims are statements about an entity (usually the user) and additional metadata. There are three types of claims:

  1. Registered claims: Predefined, e.g., iss (issuer), exp (expiration), sub (subject)
  2. Public claims: Custom claims with public names
  3. Private claims: Custom claims agreed upon between parties

Example:

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

3. Signature

To create the signature:

HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)

The signature ensures that the token wasn’t altered.

How JWT Works

  1. User logs in with credentials.
  2. Server validates the credentials.
  3. Server generates a JWT with a secret key.
  4. JWT is sent to the client.
  5. Client stores the JWT (localStorage, sessionStorage, or cookie).
  6. Client sends the JWT with each subsequent request (usually in the Authorization header).
  7. Server validates the token to allow access to protected resources.

JWT Flow Diagram

```mermaid
graph TD;
A[User Login] --> B[Server Verifies Credentials]
B --> C[Server Generates JWT]
C --> D[JWT Sent to Client]
D --> E[Client Stores JWT]
E --> F[Client Sends JWT in Requests]
F --> G[Server Verifies JWT]
G --> H[Access Granted to Protected Resources]
```

Implementing JWT in Node.js (Example)

We will use Express.js and jsonwebtoken package.

Install Dependencies

npm install express jsonwebtoken body-parser

Example Code

const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');

const app = express();
app.use(bodyParser.json());

const SECRET_KEY = 'your_secret_key';

// Dummy user data
const users = [
{ id: 1, username: 'john', password: 'password123' }
];

// Login Route
app.post('/login', (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username && u.password === password);

if (user) {
// Generate JWT
const token = jwt.sign({ id: user.id, username: user.username }, SECRET_KEY, { expiresIn: '1h' });
res.json({ token });
} else {
res.status(401).json({ message: 'Invalid credentials' });
}
});

// Middleware to verify JWT
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN

if (!token) return res.sendStatus(401);

jwt.verify(token, SECRET_KEY, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}

// Protected Route
app.get('/protected', authenticateToken, (req, res) => {
res.json({ message: 'Protected data', user: req.user });
});

app.listen(3000, () => console.log('Server running on port 3000'));

How It Works

  1. Login: Client sends credentials to /login.
  2. Generate Token: Server generates JWT if credentials are valid.
  3. Send Token: Token is sent back to client.
  4. Send Requests: Client includes token in Authorization header.
  5. Verify Token: Server checks token validity for protected routes.

Benefits of JWT

  1. Stateless Authentication: No need to store session info on the server.
  2. Compact & Portable: Can be sent via URL, headers, or cookies.
  3. Secure: Can be signed and optionally encrypted.
  4. Cross-platform: Works in web, mobile, and desktop apps.

Conclusion

JWT provides a secure and scalable way to handle authentication in modern web applications. It is widely used in REST APIs, SPAs, and mobile apps due to its stateless nature and simplicity.