JSON Web Token implementation (symmetric and asymmetric)
The jsonwebtoken package is the de facto standard for implementing JSON Web Tokens in Node.js applications. With over 31 million weekly downloads, it provides a battle-tested API for creating, verifying, and decoding JWTs—compact, URL-safe tokens that securely transmit claims between parties. The package implements RFC 7519 and supports both symmetric algorithms (HMAC with SHA-256/384/512) and asymmetric cryptography (RSA, ECDSA) for signing tokens.
JWTs solve the problem of stateless authentication in distributed systems. Unlike session-based auth that requires server-side storage, JWTs encode user identity and permissions directly in the token itself. The server validates the cryptographic signature on each request without database lookups, making this approach ideal for microservices, REST APIs, and applications that need horizontal scaling. The token payload is base64-encoded JSON, human-readable but tamper-proof when properly signed.
Developers use jsonwebtoken to issue access tokens after login, protect API endpoints by verifying tokens in middleware, and transmit claims like user roles or permissions. The package handles critical security concerns including expiration validation, audience checking, and issuer verification. It operates synchronously for simple use cases or asynchronously with callbacks when signing with RSA/ECDSA keys requires I/O operations.
The library's maturity and simplicity make it the first choice for Node.js authentication. It exposes three core methods—sign, verify, and decode—with minimal configuration needed for basic workflows. The widespread adoption means abundant community resources, framework integrations (Express, Fastify, NestJS), and proven reliability in production environments handling billions of tokens daily.
import express from 'express';
import jwt from 'jsonwebtoken';
const app = express();
const SECRET = process.env.JWT_SECRET || 'your-256-bit-secret';
app.use(express.json());
// Login endpoint - issue JWT
app.post('/login', (req, res) => {
const { username, password } = req.body;
// Verify credentials (simplified)
if (username === 'demo' && password === 'pass') {
const payload = {
sub: '12345',
username: 'demo',
role: 'admin'
};
const token = jwt.sign(payload, SECRET, {
expiresIn: '15m',
issuer: 'myapp',
audience: 'myapp-api'
});
return res.json({ token });
}
res.status(401).json({ error: 'Invalid credentials' });
});
// Middleware - verify JWT
const authenticate = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader?.startsWith('Bearer ')) {
return res.status(401).json({ error: 'No token provided' });
}
const token = authHeader.substring(7);
try {
const decoded = jwt.verify(token, SECRET, {
issuer: 'myapp',
audience: 'myapp-api'
});
req.user = decoded;
next();
} catch (err) {
if (err.name === 'TokenExpiredError') {
return res.status(401).json({ error: 'Token expired' });
}
return res.status(403).json({ error: 'Invalid token' });
}
};
// Protected route
app.get('/profile', authenticate, (req, res) => {
res.json({
message: 'Protected data',
user: req.user
});
});
app.listen(3000);User authentication in REST APIs: After validating credentials, issue a JWT containing the user ID and role. Clients include this token in the Authorization header for subsequent requests. Middleware verifies the token on protected routes, extracting user context without database queries.
Microservices authorization: Service A issues a JWT when authenticating a user. Services B and C verify the same token using a shared secret or public key, enabling single sign-on across your architecture without coupling services to a central session store.
Password reset flows: Generate short-lived tokens (15-30 minutes) embedding the user's email and a reset intent claim. Email the token as a URL parameter. When the user submits a new password, verify the token hasn't expired and extract the email to update the correct account.
API rate limiting and feature flags: Embed custom claims like subscription tier or feature entitlements in the token payload. Backend services read these claims to enforce rate limits or toggle functionality without hitting a database on every request.
Temporary resource access: Create tokens granting time-limited access to specific resources (file downloads, video streams). The token includes resource IDs and expires quickly. Services verify the token and check claims match the requested resource before serving content.
npm install jsonwebtokenpnpm add jsonwebtokenbun add jsonwebtoken