JSON Web Tokens (JWT) are a compact, URL-safe means of representing claims to be transferred between two parties. They are widely used for authentication in APIs, allowing secure and efficient communication between clients and servers. In this article, we will explore three practical examples of JWT (JSON Web Token) authentication that highlight its versatility and effectiveness in various scenarios.
In a typical web application, users need to log in to access secure resources. JWT is often used to authenticate users and maintain their session.
A user submits their credentials (username and password) to the server. Upon successful authentication, the server generates a JWT token and sends it back to the client. The client then includes this token in the header of subsequent requests to access protected resources.
// Node.js/Express example
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.json());
// Mock user data
const users = [{ username: 'test', password: 'password123' }];
app.post('/login', (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username && u.password === password);
if (user) {
const token = jwt.sign({ username: user.username }, 'secretKey', { expiresIn: '1h' });
return res.json({ token });
}
return res.status(401).send('Invalid credentials');
});
app.listen(3000, () => console.log('Server running on http://localhost:3000'));
'secretKey'
with a strong, secure key in production.Once a user has logged in and received a JWT, every request to access protected resources must include this token. A middleware function can be employed to verify the token on the server side before proceeding with the request.
This example demonstrates how to create a middleware function that checks the validity of the JWT.
// Middleware for token verification
const verifyToken = (req, res, next) => {
const token = req.headers['authorization']?.split(' ')[1];
if (!token) return res.sendStatus(403);
jwt.verify(token, 'secretKey', (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
};
// Protected route
app.get('/protected', verifyToken, (req, res) => {
res.send(`Hello ${req.user.username}, you have access to this resource!`);
});
JWT tokens typically have an expiration time for security reasons. To enhance user experience, a refresh token mechanism can be implemented. This allows users to obtain a new access token without requiring them to log in again.
In this example, we will show how to implement a refresh token endpoint.
let refreshTokens = [];
app.post('/token', (req, res) => {
const { token } = req.body;
if (!token || !refreshTokens.includes(token)) return res.sendStatus(403);
jwt.verify(token, 'refreshSecretKey', (err, user) => {
if (err) return res.sendStatus(403);
const newAccessToken = jwt.sign({ username: user.username }, 'secretKey', { expiresIn: '15m' });
res.json({ accessToken: newAccessToken });
});
});
app.post('/login', (req, res) => {
// After successful login
const refreshToken = jwt.sign({ username: user.username }, 'refreshSecretKey');
refreshTokens.push(refreshToken);
res.json({ refreshToken });
});