jsonwebtoken (Node.js)
Library
jsonwebtoken (Node.js)
Overview
jsonwebtoken is a JSON Web Token (JWT) library for Node.js developed and maintained by Auth0. As of 2025, it has become one of the most popular JWT libraries with over 28 million weekly downloads on npm and is used by over 34,000 projects. As an RFC 7519-compliant JWT implementation, it supports both symmetric and asymmetric signing algorithms, with full support for major algorithms including HS256, RS256, and ES256. In addition to basic functions for token generation (jwt.sign), verification (jwt.verify), and decoding (jwt.decode), it provides expiration time settings, custom claims, and asynchronous processing support. It integrates easily with web frameworks like Express.js, Hapi, and Koa, and has been widely adopted as an industry standard for building authentication and authorization systems.
Details
jsonwebtoken 9.x series supports Node.js 12 and above, providing high-performance JWT processing leveraging the latest JavaScript (ES2020+) features. As core functionality, it provides three interfaces: Promise-based asynchronous API, callback-based traditional API, and synchronous processing API, accommodating diverse development styles. From a security perspective, it supports a wide range of signing algorithms including HMAC-SHA256 (HS256), RSA-SHA256 (RS256), and ECDSA-SHA256 (ES256), and also supports key management and rotation. With performance optimization, it achieves high-speed operation even when processing large volumes of tokens, making it applicable to enterprise-level applications.
Key Features
- Comprehensive JWT Implementation: RFC 7519 fully compliant token generation, verification, and decoding functions
- Diverse Signing Algorithms: Support for HS256/HS384/HS512, RS256/RS384/RS512, ES256/ES384/ES512
- Flexible API Design: Three interfaces - synchronous, asynchronous, and Promise-based
- Advanced Security: Expiration, issuer, audience validation and custom claims support
- Excellent Compatibility: Integration track record with major Node.js frameworks
- Enterprise Ready: High performance and reliability in large-scale environments
Advantages and Disadvantages
Advantages
- High reliability and stability through long-term maintenance track record by Auth0
- Rich implementation examples and information volume with over 28 million weekly npm downloads
- Complete compatibility with other JWT implementations guaranteed by RFC 7519 full compliance
- Support for diverse development styles through three API patterns - synchronous, asynchronous, and Promise
- Flexible response to security requirements through wide range of signing algorithm support from HS256 to ES512
- Easy integration with web frameworks like Express.js for high development efficiency
Disadvantages
- Node.js-specific library, cannot be used directly in browser environments
- CPU usage may increase when verifying large volumes of tokens
- Key management complexity increases when using asymmetric signatures (RS256, etc.)
- TypeScript type definitions provided in separate package (@types/jsonwebtoken)
- Improper security configuration may create vulnerabilities
- Additional implementation required for complex claim validation logic
Reference Pages
Usage Examples
Basic Setup and Dependency Installation
# Install jsonwebtoken library
npm install jsonwebtoken
# Install type definitions for TypeScript usage
npm install --save-dev @types/jsonwebtoken
# Additional packages for security enhancement (optional)
npm install crypto
npm install dotenv # For environment variable management
// Basic require statement (CommonJS)
const jwt = require('jsonwebtoken');
// ES6 import statement (when using modules)
import jwt from 'jsonwebtoken';
// Typed import for TypeScript environment
import * as jwt from 'jsonwebtoken';
// package.json configuration example
{
"name": "jwt-auth-app",
"version": "1.0.0",
"dependencies": {
"jsonwebtoken": "^9.0.2",
"express": "^4.18.2",
"dotenv": "^16.3.1"
},
"devDependencies": {
"@types/jsonwebtoken": "^9.0.3",
"@types/node": "^20.5.0"
}
}
JWT Token Generation and Custom Claims Configuration
// JWTTokenService.js - Token generation service
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
class JWTTokenService {
constructor() {
// Get secret key from environment variables (required in production)
this.secretKey = process.env.JWT_SECRET || this.generateSecretKey();
this.issuer = process.env.JWT_ISSUER || 'your-app-name';
this.audience = process.env.JWT_AUDIENCE || 'your-app-users';
}
// Generate secure secret key
generateSecretKey() {
return crypto.randomBytes(64).toString('hex');
}
// Basic JWT token generation
generateToken(payload, options = {}) {
// Default options configuration
const defaultOptions = {
expiresIn: '1h', // Valid for 1 hour
issuer: this.issuer, // Issuer
audience: this.audience, // Audience
algorithm: 'HS256' // Signing algorithm
};
const finalOptions = { ...defaultOptions, ...options };
try {
// Synchronous token generation
const token = jwt.sign(payload, this.secretKey, finalOptions);
console.log('JWT token generated successfully');
return token;
} catch (error) {
console.error('JWT token generation failed:', error.message);
throw new Error('Token generation failed');
}
}
// Asynchronous token generation (Callback version)
generateTokenAsync(payload, options = {}, callback) {
const defaultOptions = {
expiresIn: '1h',
issuer: this.issuer,
audience: this.audience,
algorithm: 'HS256'
};
const finalOptions = { ...defaultOptions, ...options };
jwt.sign(payload, this.secretKey, finalOptions, (error, token) => {
if (error) {
console.error('Async JWT token generation failed:', error.message);
return callback(error, null);
}
console.log('Async JWT token generated successfully');
callback(null, token);
});
}
// Promise-based asynchronous token generation
generateTokenPromise(payload, options = {}) {
return new Promise((resolve, reject) => {
this.generateTokenAsync(payload, options, (error, token) => {
if (error) {
reject(error);
} else {
resolve(token);
}
});
});
}
// User authentication token generation
generateUserToken(user) {
const payload = {
sub: user.id, // Subject (User ID)
username: user.username,
email: user.email,
roles: user.roles || ['user'],
permissions: user.permissions || [],
iat: Math.floor(Date.now() / 1000) // Issued at time
};
return this.generateToken(payload, {
expiresIn: '2h',
subject: user.id
});
}
// Refresh token generation
generateRefreshToken(userId) {
const payload = {
sub: userId,
type: 'refresh',
iat: Math.floor(Date.now() / 1000)
};
return this.generateToken(payload, {
expiresIn: '7d', // Valid for 7 days
subject: userId
});
}
// Admin-only token generation
generateAdminToken(admin) {
const payload = {
sub: admin.id,
username: admin.username,
email: admin.email,
roles: ['admin'],
permissions: admin.permissions || ['read', 'write', 'delete'],
isAdmin: true,
department: admin.department,
iat: Math.floor(Date.now() / 1000)
};
return this.generateToken(payload, {
expiresIn: '1h', // Short expiration for admin tokens
audience: this.audience + '-admin'
});
}
// Temporary access token generation (password reset, etc.)
generateTemporaryToken(userId, purpose) {
const payload = {
sub: userId,
purpose: purpose, // 'password-reset', 'email-verify', etc.
temp: true,
iat: Math.floor(Date.now() / 1000)
};
return this.generateToken(payload, {
expiresIn: '15m', // Valid for 15 minutes only
audience: this.audience + '-temp'
});
}
}
// Usage examples
const tokenService = new JWTTokenService();
// User information
const user = {
id: '12345',
username: 'johndoe',
email: '[email protected]',
roles: ['user', 'premium'],
permissions: ['read', 'write']
};
// Various token generation examples
const userToken = tokenService.generateUserToken(user);
const refreshToken = tokenService.generateRefreshToken(user.id);
const resetToken = tokenService.generateTemporaryToken(user.id, 'password-reset');
console.log('User Token:', userToken);
console.log('Refresh Token:', refreshToken);
console.log('Reset Token:', resetToken);
module.exports = JWTTokenService;
JWT Token Verification and Security Checks
// JWTVerificationService.js - Token verification service
const jwt = require('jsonwebtoken');
class JWTVerificationService {
constructor(secretKey, options = {}) {
this.secretKey = secretKey || process.env.JWT_SECRET;
this.issuer = options.issuer || process.env.JWT_ISSUER;
this.audience = options.audience || process.env.JWT_AUDIENCE;
this.algorithms = options.algorithms || ['HS256'];
}
// Basic token verification
verifyToken(token, options = {}) {
const defaultOptions = {
issuer: this.issuer,
audience: this.audience,
algorithms: this.algorithms,
clockTolerance: 30, // 30 second clock tolerance
ignoreExpiration: false,
ignoreNotBefore: false
};
const finalOptions = { ...defaultOptions, ...options };
try {
// Synchronous token verification
const decoded = jwt.verify(token, this.secretKey, finalOptions);
console.log('JWT token verified successfully');
return {
success: true,
payload: decoded,
error: null
};
} catch (error) {
console.error('JWT token verification failed:', error.message);
return {
success: false,
payload: null,
error: this.categorizeError(error)
};
}
}
// Asynchronous token verification (Callback version)
verifyTokenAsync(token, options = {}, callback) {
const defaultOptions = {
issuer: this.issuer,
audience: this.audience,
algorithms: this.algorithms,
clockTolerance: 30
};
const finalOptions = { ...defaultOptions, ...options };
jwt.verify(token, this.secretKey, finalOptions, (error, decoded) => {
if (error) {
console.error('Async JWT token verification failed:', error.message);
return callback({
success: false,
payload: null,
error: this.categorizeError(error)
});
}
console.log('Async JWT token verified successfully');
callback({
success: true,
payload: decoded,
error: null
});
});
}
// Promise-based asynchronous token verification
verifyTokenPromise(token, options = {}) {
return new Promise((resolve, reject) => {
this.verifyTokenAsync(token, options, (result) => {
if (result.success) {
resolve(result);
} else {
reject(result);
}
});
});
}
// Error categorization
categorizeError(error) {
if (error.name === 'TokenExpiredError') {
return {
type: 'EXPIRED',
message: 'Token has expired',
expiredAt: error.expiredAt
};
} else if (error.name === 'JsonWebTokenError') {
return {
type: 'INVALID',
message: 'Token is invalid',
details: error.message
};
} else if (error.name === 'NotBeforeError') {
return {
type: 'NOT_ACTIVE',
message: 'Token not active',
date: error.date
};
} else {
return {
type: 'UNKNOWN',
message: 'Unknown verification error',
details: error.message
};
}
}
// Token decoding (without verification)
decodeToken(token, options = {}) {
const defaultOptions = {
complete: false, // true returns header, payload, signature
json: true // return as JSON object
};
const finalOptions = { ...defaultOptions, ...options };
try {
const decoded = jwt.decode(token, finalOptions);
return {
success: true,
payload: decoded,
error: null
};
} catch (error) {
return {
success: false,
payload: null,
error: error.message
};
}
}
// Admin privileges check
verifyAdminToken(token) {
const result = this.verifyToken(token, {
audience: this.audience + '-admin'
});
if (!result.success) {
return result;
}
// Admin privileges check
if (!result.payload.isAdmin || !result.payload.roles.includes('admin')) {
return {
success: false,
payload: null,
error: {
type: 'INSUFFICIENT_PRIVILEGES',
message: 'Admin privileges required'
}
};
}
return result;
}
// User permissions check
verifyUserPermissions(token, requiredPermissions = []) {
const result = this.verifyToken(token);
if (!result.success) {
return result;
}
const userPermissions = result.payload.permissions || [];
const hasAllPermissions = requiredPermissions.every(permission =>
userPermissions.includes(permission)
);
if (!hasAllPermissions) {
return {
success: false,
payload: null,
error: {
type: 'INSUFFICIENT_PERMISSIONS',
message: 'Required permissions not found',
required: requiredPermissions,
current: userPermissions
}
};
}
return result;
}
// Refresh token verification
verifyRefreshToken(token) {
const result = this.verifyToken(token);
if (!result.success) {
return result;
}
// Refresh token type check
if (result.payload.type !== 'refresh') {
return {
success: false,
payload: null,
error: {
type: 'INVALID_TOKEN_TYPE',
message: 'Not a refresh token'
}
};
}
return result;
}
// Temporary token verification
verifyTemporaryToken(token, expectedPurpose) {
const result = this.verifyToken(token, {
audience: this.audience + '-temp'
});
if (!result.success) {
return result;
}
// Check if temporary token and purpose matches
if (!result.payload.temp || result.payload.purpose !== expectedPurpose) {
return {
success: false,
payload: null,
error: {
type: 'INVALID_PURPOSE',
message: 'Token purpose mismatch',
expected: expectedPurpose,
actual: result.payload.purpose
}
};
}
return result;
}
}
// Usage examples
const verificationService = new JWTVerificationService(process.env.JWT_SECRET, {
issuer: 'your-app-name',
audience: 'your-app-users'
});
// Token verification example
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
// Basic verification
const result = verificationService.verifyToken(token);
if (result.success) {
console.log('Token is valid:', result.payload);
} else {
console.log('Token verification failed:', result.error);
}
// Admin privileges check
const adminResult = verificationService.verifyAdminToken(token);
// Permissions check
const permissionResult = verificationService.verifyUserPermissions(token, ['read', 'write']);
module.exports = JWTVerificationService;
Express.js Middleware Integration and Authentication Flow
// JWTMiddleware.js - Express.js JWT middleware
const jwt = require('jsonwebtoken');
const JWTVerificationService = require('./JWTVerificationService');
class JWTMiddleware {
constructor(secretKey, options = {}) {
this.verificationService = new JWTVerificationService(secretKey, options);
this.cookieName = options.cookieName || 'auth_token';
this.headerName = options.headerName || 'authorization';
}
// Basic authentication middleware
authenticate() {
return (req, res, next) => {
const token = this.extractToken(req);
if (!token) {
return res.status(401).json({
error: 'Authentication required',
message: 'No token provided'
});
}
const result = this.verificationService.verifyToken(token);
if (!result.success) {
return res.status(401).json({
error: 'Invalid token',
message: result.error.message,
type: result.error.type
});
}
// Add user information to request
req.user = result.payload;
req.token = token;
next();
};
}
// Optional authentication middleware
optionalAuthenticate() {
return (req, res, next) => {
const token = this.extractToken(req);
if (!token) {
req.user = null;
return next();
}
const result = this.verificationService.verifyToken(token);
if (result.success) {
req.user = result.payload;
req.token = token;
} else {
req.user = null;
}
next();
};
}
// Admin privileges check middleware
requireAdmin() {
return (req, res, next) => {
const token = this.extractToken(req);
if (!token) {
return res.status(401).json({
error: 'Authentication required',
message: 'Admin access requires token'
});
}
const result = this.verificationService.verifyAdminToken(token);
if (!result.success) {
return res.status(403).json({
error: 'Access denied',
message: result.error.message,
type: result.error.type
});
}
req.user = result.payload;
req.token = token;
next();
};
}
// Permissions check middleware
requirePermissions(permissions = []) {
return (req, res, next) => {
const token = this.extractToken(req);
if (!token) {
return res.status(401).json({
error: 'Authentication required',
message: 'Permission check requires token'
});
}
const result = this.verificationService.verifyUserPermissions(token, permissions);
if (!result.success) {
return res.status(403).json({
error: 'Insufficient permissions',
message: result.error.message,
required: result.error.required,
current: result.error.current
});
}
req.user = result.payload;
req.token = token;
next();
};
}
// Role check middleware
requireRoles(roles = []) {
return (req, res, next) => {
const token = this.extractToken(req);
if (!token) {
return res.status(401).json({
error: 'Authentication required'
});
}
const result = this.verificationService.verifyToken(token);
if (!result.success) {
return res.status(401).json({
error: 'Invalid token',
message: result.error.message
});
}
const userRoles = result.payload.roles || [];
const hasRequiredRole = roles.some(role => userRoles.includes(role));
if (!hasRequiredRole) {
return res.status(403).json({
error: 'Insufficient role',
message: 'Required role not found',
required: roles,
current: userRoles
});
}
req.user = result.payload;
req.token = token;
next();
};
}
// Token extraction logic
extractToken(req) {
// Extract token from Authorization header
const authHeader = req.headers[this.headerName];
if (authHeader && authHeader.startsWith('Bearer ')) {
return authHeader.substring(7);
}
// Extract token from Cookie
if (req.cookies && req.cookies[this.cookieName]) {
return req.cookies[this.cookieName];
}
// Extract token from query parameter (deprecated but for emergency use)
if (req.query && req.query.token) {
return req.query.token;
}
return null;
}
}
// Express.js application integration example
const express = require('express');
const cookieParser = require('cookie-parser');
const JWTTokenService = require('./JWTTokenService');
const app = express();
const tokenService = new JWTTokenService();
const jwtMiddleware = new JWTMiddleware(process.env.JWT_SECRET, {
issuer: 'your-app-name',
audience: 'your-app-users'
});
// Basic middleware configuration
app.use(express.json());
app.use(cookieParser());
// Login endpoint
app.post('/auth/login', async (req, res) => {
try {
const { username, password } = req.body;
// Authentication logic (use external authentication system in production)
const user = await authenticateUser(username, password);
if (!user) {
return res.status(401).json({
error: 'Authentication failed',
message: 'Invalid credentials'
});
}
// Token generation
const accessToken = tokenService.generateUserToken(user);
const refreshToken = tokenService.generateRefreshToken(user.id);
// Set token in cookie
res.cookie('auth_token', accessToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 2 * 60 * 60 * 1000 // 2 hours
});
res.json({
message: 'Login successful',
user: {
id: user.id,
username: user.username,
email: user.email,
roles: user.roles
},
tokens: {
accessToken,
refreshToken,
expiresIn: 7200 // 2 hours (seconds)
}
});
} catch (error) {
res.status(500).json({
error: 'Internal server error',
message: error.message
});
}
});
// Protected route example
app.get('/api/profile',
jwtMiddleware.authenticate(),
(req, res) => {
res.json({
message: 'Profile data',
user: req.user
});
}
);
// Admin-only route example
app.get('/api/admin/users',
jwtMiddleware.requireAdmin(),
(req, res) => {
res.json({
message: 'Admin users data',
admin: req.user
});
}
);
// Route requiring permissions check
app.post('/api/posts',
jwtMiddleware.requirePermissions(['write']),
(req, res) => {
res.json({
message: 'Post created successfully',
user: req.user
});
}
);
// Route requiring role check
app.get('/api/reports',
jwtMiddleware.requireRoles(['premium', 'admin']),
(req, res) => {
res.json({
message: 'Reports data',
user: req.user
});
}
);
// Token refresh endpoint
app.post('/auth/refresh', (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken) {
return res.status(401).json({
error: 'Refresh token required'
});
}
const result = jwtMiddleware.verificationService.verifyRefreshToken(refreshToken);
if (!result.success) {
return res.status(401).json({
error: 'Invalid refresh token',
message: result.error.message
});
}
// Generate new access token
const newAccessToken = tokenService.generateToken({
sub: result.payload.sub
});
res.json({
accessToken: newAccessToken,
expiresIn: 3600
});
});
// Logout endpoint
app.post('/auth/logout',
jwtMiddleware.authenticate(),
(req, res) => {
// Clear cookie
res.clearCookie('auth_token');
res.json({
message: 'Logout successful'
});
}
);
async function authenticateUser(username, password) {
// Actual authentication logic (database, LDAP, etc.)
// Dummy implementation here
if (username === 'admin' && password === 'password') {
return {
id: '1',
username: 'admin',
email: '[email protected]',
roles: ['admin', 'user'],
permissions: ['read', 'write', 'delete']
};
}
return null;
}
module.exports = { JWTMiddleware, app };
Asymmetric Encryption (RS256) and Security Enhancement
// RSAJWTService.js - JWT service using RSA key pairs
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
class RSAJWTService {
constructor(options = {}) {
this.algorithm = 'RS256';
this.issuer = options.issuer || process.env.JWT_ISSUER;
this.audience = options.audience || process.env.JWT_AUDIENCE;
// Load RSA key pair
this.loadKeyPair();
}
// Load RSA key pair
loadKeyPair() {
try {
// Private and public key paths
const privateKeyPath = process.env.JWT_PRIVATE_KEY_PATH || path.join(__dirname, 'keys', 'private.pem');
const publicKeyPath = process.env.JWT_PUBLIC_KEY_PATH || path.join(__dirname, 'keys', 'public.pem');
// Generate key files if they don't exist
if (!fs.existsSync(privateKeyPath) || !fs.existsSync(publicKeyPath)) {
this.generateKeyPair();
}
this.privateKey = fs.readFileSync(privateKeyPath, 'utf8');
this.publicKey = fs.readFileSync(publicKeyPath, 'utf8');
console.log('RSA key pair loaded successfully');
} catch (error) {
console.error('Failed to load RSA key pair:', error.message);
throw new Error('RSA key pair initialization failed');
}
}
// Generate RSA key pair
generateKeyPair() {
const keysDir = path.join(__dirname, 'keys');
// Create keys directory if it doesn't exist
if (!fs.existsSync(keysDir)) {
fs.mkdirSync(keysDir, { recursive: true });
}
// Generate 2048-bit RSA key pair
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem'
}
});
// Save key files
fs.writeFileSync(path.join(keysDir, 'private.pem'), privateKey);
fs.writeFileSync(path.join(keysDir, 'public.pem'), publicKey);
console.log('New RSA key pair generated and saved');
}
// Generate token with RSA signature
generateToken(payload, options = {}) {
const defaultOptions = {
algorithm: this.algorithm,
expiresIn: '1h',
issuer: this.issuer,
audience: this.audience,
keyid: 'rsa-key-1' // Key ID (useful for multiple key management)
};
const finalOptions = { ...defaultOptions, ...options };
try {
// Sign with RSA private key
const token = jwt.sign(payload, this.privateKey, finalOptions);
console.log('RSA JWT token generated successfully');
return token;
} catch (error) {
console.error('RSA JWT token generation failed:', error.message);
throw new Error('RSA token generation failed');
}
}
// Verify token with RSA public key
verifyToken(token, options = {}) {
const defaultOptions = {
algorithms: [this.algorithm],
issuer: this.issuer,
audience: this.audience,
clockTolerance: 30
};
const finalOptions = { ...defaultOptions, ...options };
try {
// Verify with RSA public key
const decoded = jwt.verify(token, this.publicKey, finalOptions);
console.log('RSA JWT token verified successfully');
return {
success: true,
payload: decoded,
error: null
};
} catch (error) {
console.error('RSA JWT token verification failed:', error.message);
return {
success: false,
payload: null,
error: this.categorizeError(error)
};
}
}
// Get public key information for JWKS endpoint
getPublicKeyJWKS() {
const keyObject = crypto.createPublicKey(this.publicKey);
const jwk = keyObject.export({ format: 'jwk' });
return {
keys: [{
kty: jwk.kty,
use: 'sig',
kid: 'rsa-key-1',
alg: 'RS256',
n: jwk.n,
e: jwk.e
}]
};
}
// Advanced token generation (with custom headers)
generateAdvancedToken(payload, customHeaders = {}) {
const headers = {
typ: 'JWT',
alg: this.algorithm,
kid: 'rsa-key-1',
...customHeaders
};
const token = jwt.sign(payload, this.privateKey, {
algorithm: this.algorithm,
expiresIn: '1h',
issuer: this.issuer,
audience: this.audience,
header: headers
});
return token;
}
// Key rotation support
rotateKeys() {
try {
// Backup current keys
const backupDir = path.join(__dirname, 'keys', 'backup');
if (!fs.existsSync(backupDir)) {
fs.mkdirSync(backupDir, { recursive: true });
}
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
fs.copyFileSync(
path.join(__dirname, 'keys', 'private.pem'),
path.join(backupDir, `private-${timestamp}.pem`)
);
fs.copyFileSync(
path.join(__dirname, 'keys', 'public.pem'),
path.join(backupDir, `public-${timestamp}.pem`)
);
// Generate new key pair
this.generateKeyPair();
this.loadKeyPair();
console.log('Key rotation completed successfully');
return true;
} catch (error) {
console.error('Key rotation failed:', error.message);
return false;
}
}
// Generate security report
generateSecurityReport(tokens = []) {
const report = {
timestamp: new Date().toISOString(),
algorithm: this.algorithm,
keyStatus: 'active',
tokensAnalyzed: tokens.length,
validTokens: 0,
expiredTokens: 0,
invalidTokens: 0,
securityIssues: []
};
tokens.forEach(token => {
const result = this.verifyToken(token);
if (result.success) {
report.validTokens++;
// Security check
const payload = result.payload;
if (!payload.exp || (payload.exp - payload.iat) > 86400) {
report.securityIssues.push('Long-lived token detected');
}
} else if (result.error.type === 'EXPIRED') {
report.expiredTokens++;
} else {
report.invalidTokens++;
}
});
return report;
}
categorizeError(error) {
if (error.name === 'TokenExpiredError') {
return {
type: 'EXPIRED',
message: 'Token has expired',
expiredAt: error.expiredAt
};
} else if (error.name === 'JsonWebTokenError') {
return {
type: 'INVALID',
message: 'Token is invalid',
details: error.message
};
} else if (error.name === 'NotBeforeError') {
return {
type: 'NOT_ACTIVE',
message: 'Token not active',
date: error.date
};
} else {
return {
type: 'UNKNOWN',
message: 'Unknown verification error',
details: error.message
};
}
}
}
// Usage examples and Express.js integration
const express = require('express');
const app = express();
const rsaJWTService = new RSAJWTService({
issuer: 'secure-app',
audience: 'secure-app-users'
});
app.use(express.json());
// JWKS endpoint (public key distribution)
app.get('/.well-known/jwks.json', (req, res) => {
res.json(rsaJWTService.getPublicKeyJWKS());
});
// RSA signed token generation endpoint
app.post('/auth/rsa-login', (req, res) => {
const { username, password } = req.body;
// Authentication process (omitted)
const user = { id: 1, username: 'testuser', roles: ['user'] };
const token = rsaJWTService.generateToken({
sub: user.id,
username: user.username,
roles: user.roles
});
res.json({
token,
algorithm: 'RS256',
message: 'RSA signed token generated'
});
});
// RSA verification middleware
const requireRSAAuth = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Token required' });
}
const token = authHeader.substring(7);
const result = rsaJWTService.verifyToken(token);
if (!result.success) {
return res.status(401).json({
error: 'Invalid token',
details: result.error
});
}
req.user = result.payload;
next();
};
// Protected route
app.get('/api/secure-data', requireRSAAuth, (req, res) => {
res.json({
message: 'Secure data accessed with RSA verification',
user: req.user
});
});
// Key rotation management endpoint (admin only)
app.post('/admin/rotate-keys', requireRSAAuth, (req, res) => {
if (!req.user.roles.includes('admin')) {
return res.status(403).json({ error: 'Admin access required' });
}
const success = rsaJWTService.rotateKeys();
if (success) {
res.json({ message: 'Key rotation completed successfully' });
} else {
res.status(500).json({ error: 'Key rotation failed' });
}
});
module.exports = RSAJWTService;