Muestras JWT
Ejemplos completos de JWT desde la estructura básica de tokens hasta implementaciones de seguridad avanzadas
Key Facts
- Category
- Security
- Items
- 6
- Format Families
- json, text
Sample Overview
Ejemplos completos de JWT desde la estructura básica de tokens hasta implementaciones de seguridad avanzadas This sample set belongs to Security and can be used to test related workflows inside Elysia Tools.
📝 Token JWT
Comprender los tokens JWT
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiJZekV6TUdkb01ISm5PSEJpT0cxaWJEaHlOVEE9IiwicmVzcG9uc2VfdHlwZSI6ImNvZGUiLCJzY29wZSI6ImludHJvc2NwZWN0X3Rva2VucywgcmV2b2tlX3Rva2VucyIsImlzcyI6ImJqaElSak0xY1hwYWEyMXpkV3RJU25wNmVqbE1iazQ0YlRsTlpqazNkWEU9Iiwic3ViIjoiWXpFek1HZG9NSEpuT0hCaU9HMWliRGh5TlRBPSIsImF1ZCI6Imh0dHBzOi8vbG9jYWxob3N0Ojg0NDMve3RpZH0ve2FpZH0vb2F1dGgyL2F1dGhvcml6ZSIsImp0aSI6IjE1MTYyMzkwMjIiLCJleHAiOiIyMDIxLTA1LTE3VDA3OjA5OjQ4LjAwMCswNTQ1In0.IxvaN4ER-PlPgLYzfRhk_JiY4VAow3GNjaK5rYCINFsEPa7VaYnRsaCmQVq8CTgddihEPPXet2laH8_c3WqxY4AeZO5eljwSCobCHzxYdOoFKbpNXIm7dqHg_5xpQz-YBJMiDM1ILOEsER8ADyF4NC2sN0K_0t6xZLSAQIRrHvpGOrtYr5E-SllTWHWPmqCkX2BUZxoYNK2FWgQZpuUOD55HfsvFXNVQa_5TFRDibi9LsT7Sd_az0iGB0TfAb0v3ZR0qnmgyp5pTeIeU5UqhtbgU9RnUCVmGIK-SZYNvrlXgv9hiKAZGhLgeI8hO40utfT2YTYHgD2Aiufqo3RIbJA
💻 Creación y Verificación de Tokens JWT en Node.js javascript
Crear y verificar tokens JWT en Node.js usando la librería jsonwebtoken
const jwt = require('jsonwebtoken');
// JWT Secret Key (store this securely!)
const SECRET_KEY = 'your-super-secret-key-change-in-production';
// User data to be included in token
const userPayload = {
userId: '12345',
email: '[email protected]',
role: 'user'
};
// Create JWT Token
function createJWT(payload, expiresIn = '1h') {
return jwt.sign(payload, SECRET_KEY, {
expiresIn: expiresIn,
algorithm: 'HS256',
issuer: 'your-api.com',
audience: 'your-app.com'
});
}
// Verify JWT Token
function verifyJWT(token) {
try {
const decoded = jwt.verify(token, SECRET_KEY);
console.log('Token is valid:', decoded);
return decoded;
} catch (error) {
console.error('Token verification failed:', error.message);
return null;
}
}
// Decode JWT (without verification)
function decodeJWT(token) {
const decoded = jwt.decode(token, { complete: true });
console.log('Decoded token:', decoded);
return decoded;
}
// Usage Examples
console.log('=== Creating JWT ===');
const token = createJWT(userPayload, '2h');
console.log('Generated Token:', token);
console.log('\n=== Verifying JWT ===');
const verified = verifyJWT(token);
console.log('Verified Payload:', verified);
console.log('\n=== Decoding JWT ===');
const decoded = decodeJWT(token);
console.log('Header:', decoded.header);
console.log('Payload:', decoded.payload);
// Check if token is expired
function isTokenExpired(decodedToken) {
const now = Math.floor(Date.now() / 1000);
return decodedToken.exp < now;
}
if (verified) {
console.log('Is token expired?', isTokenExpired(verified));
}
💻 Manejo de JWT en el Navegador javascript
Manejo de tokens JWT en el navegador usando interceptores de axios
// JWT Token Management in Browser
class AuthManager {
constructor() {
this.tokenKey = 'jwt_token';
this.refreshTokenKey = 'jwt_refresh_token';
}
// Store JWT token
setToken(token, rememberMe = false) {
const storage = rememberMe ? localStorage : sessionStorage;
storage.setItem(this.tokenKey, token);
// Also store expiration time
const decoded = this.decodeToken(token);
if (decoded && decoded.exp) {
storage.setItem('jwt_expires_at', decoded.exp);
}
}
// Get JWT token
getToken() {
return localStorage.getItem(this.tokenKey) ||
sessionStorage.getItem(this.tokenKey);
}
// Remove JWT token
removeToken() {
localStorage.removeItem(this.tokenKey);
sessionStorage.removeItem(this.tokenKey);
localStorage.removeItem('jwt_expires_at');
sessionStorage.removeItem('jwt_expires_at');
}
// Check if token is expired
isTokenExpired() {
const expiresAt = localStorage.getItem('jwt_expires_at') ||
sessionStorage.getItem('jwt_expires_at');
if (!expiresAt) return true;
return parseInt(expiresAt) < Math.floor(Date.now() / 1000);
}
// Decode token without verification
decodeToken(token) {
try {
const payload = JSON.parse(atob(token.split('.')[1]));
return payload;
} catch (error) {
return null;
}
}
// Get user info from token
getUserInfo() {
const token = this.getToken();
if (!token) return null;
const decoded = this.decodeToken(token);
return decoded;
}
}
// Axios Interceptors for JWT
const authManager = new AuthManager();
// Request Interceptor - Add JWT token to every request
axios.interceptors.request.use(
(config) => {
const token = authManager.getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// Response Interceptor - Handle token expiration
axios.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
// If token expired and we haven't tried to refresh yet
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
// Try to refresh token
const newToken = await refreshToken();
authManager.setToken(newToken);
// Retry the original request with new token
originalRequest.headers.Authorization = `Bearer ${newToken}`;
return axios(originalRequest);
} catch (refreshError) {
// If refresh fails, redirect to login
authManager.removeToken();
window.location.href = '/login';
return Promise.reject(refreshError);
}
}
return Promise.reject(error);
}
);
// Refresh token function
async function refreshToken() {
const refreshToken = localStorage.getItem('jwt_refresh_token');
if (!refreshToken) {
throw new Error('No refresh token available');
}
const response = await axios.post('/api/auth/refresh', {
refresh_token: refreshToken
});
return response.data.access_token;
}
// API Service with JWT
class ApiService {
async login(email, password, rememberMe = false) {
try {
const response = await axios.post('/api/auth/login', {
email,
password
});
const { access_token, refresh_token } = response.data;
authManager.setToken(access_token, rememberMe);
localStorage.setItem('jwt_refresh_token', refresh_token);
return response.data;
} catch (error) {
console.error('Login failed:', error);
throw error;
}
}
async logout() {
try {
await axios.post('/api/auth/logout');
} catch (error) {
console.error('Logout failed:', error);
} finally {
authManager.removeToken();
localStorage.removeItem('jwt_refresh_token');
}
}
async getProtectedData() {
const response = await axios.get('/api/protected/data');
return response.data;
}
}
// Usage Example
const apiService = new ApiService();
// Login
// apiService.login('[email protected]', 'password123', true)
// .then(() => console.log('Logged in successfully'))
// .catch(error => console.error('Login failed:', error));
// Access protected data
// apiService.getProtectedData()
// .then(data => console.log('Protected data:', data))
// .catch(error => console.error('Access denied:', error));
💻 Middleware JWT para Express.js javascript
Implementar middleware de autenticación JWT para Express.js
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const app = express();
app.use(express.json());
// JWT Configuration
const JWT_CONFIG = {
SECRET: 'your-super-secret-key-change-in-production',
ACCESS_TOKEN_EXPIRY: '15m',
REFRESH_TOKEN_EXPIRY: '7d',
ALGORITHM: 'HS256'
};
// Mock user database
const users = [
{
id: 1,
email: '[email protected]',
password: '$2a$10$N9qo8uLOickgx2ZMRZoMy.Mwrz2UqJ6H4f9G4UJ8T8K8W8j8jK8iK',
role: 'admin'
}
];
// JWT Middleware
const authenticateJWT = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader) {
return res.status(401).json({ message: 'Authorization header required' });
}
const token = authHeader.split(' ')[1]; // Bearer TOKEN
try {
const decoded = jwt.verify(token, JWT_CONFIG.SECRET);
req.user = decoded;
next();
} catch (error) {
if (error.name === 'TokenExpiredError') {
return res.status(401).json({ message: 'Token expired' });
} else if (error.name === 'JsonWebTokenError') {
return res.status(401).json({ message: 'Invalid token' });
} else {
return res.status(500).json({ message: 'Internal server error' });
}
}
};
// Role-based Authorization Middleware
const authorize = (roles = []) => {
return (req, res, next) => {
if (!req.user) {
return res.status(401).json({ message: 'Authentication required' });
}
if (roles.length && !roles.includes(req.user.role)) {
return res.status(403).json({ message: 'Insufficient permissions' });
}
next();
};
};
// Generate Access Token
const generateAccessToken = (user) => {
return jwt.sign(
{
userId: user.id,
email: user.email,
role: user.role
},
JWT_CONFIG.SECRET,
{
expiresIn: JWT_CONFIG.ACCESS_TOKEN_EXPIRY,
algorithm: JWT_CONFIG.ALGORITHM,
issuer: 'your-api.com',
audience: 'your-app.com'
}
);
};
// Generate Refresh Token
const generateRefreshToken = (user) => {
return jwt.sign(
{
userId: user.id,
tokenType: 'refresh'
},
JWT_CONFIG.SECRET,
{
expiresIn: JWT_CONFIG.REFRESH_TOKEN_EXPIRY,
algorithm: JWT_CONFIG.ALGORITHM
}
);
};
// Login Route
app.post('/api/auth/login', async (req, res) => {
try {
const { email, password } = req.body;
// Find user
const user = users.find(u => u.email === email);
if (!user) {
return res.status(401).json({ message: 'Invalid credentials' });
}
// Check password
const isValidPassword = await bcrypt.compare(password, user.password);
if (!isValidPassword) {
return res.status(401).json({ message: 'Invalid credentials' });
}
// Generate tokens
const accessToken = generateAccessToken(user);
const refreshToken = generateRefreshToken(user);
res.json({
access_token: accessToken,
refresh_token: refreshToken,
user: {
id: user.id,
email: user.email,
role: user.role
}
});
} catch (error) {
res.status(500).json({ message: 'Internal server error' });
}
});
// Refresh Token Route
app.post('/api/auth/refresh', (req, res) => {
try {
const { refresh_token } = req.body;
if (!refresh_token) {
return res.status(400).json({ message: 'Refresh token required' });
}
const decoded = jwt.verify(refresh_token, JWT_CONFIG.SECRET);
if (decoded.tokenType !== 'refresh') {
return res.status(401).json({ message: 'Invalid refresh token' });
}
// Find user and generate new access token
const user = users.find(u => u.id === decoded.userId);
if (!user) {
return res.status(401).json({ message: 'User not found' });
}
const newAccessToken = generateAccessToken(user);
res.json({
access_token: newAccessToken
});
} catch (error) {
res.status(401).json({ message: 'Invalid refresh token' });
}
});
// Protected Routes
app.get('/api/protected', authenticateJWT, (req, res) => {
res.json({
message: 'This is a protected route',
user: req.user
});
});
app.get('/api/admin', authenticateJWT, authorize(['admin']), (req, res) => {
res.json({
message: 'Admin access granted',
user: req.user
});
});
// Logout Route
app.post('/api/auth/logout', authenticateJWT, (req, res) => {
// In a real app, you might want to blacklist the token
res.json({ message: 'Logged out successfully' });
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
💻 Mejores Prácticas de Seguridad JWT javascript
Implementar configuración de seguridad JWT avanzada con cifrado asimétrico
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
// Advanced JWT Security Implementation
class JWTSecurityManager {
constructor(config) {
const generatedKeyPair = this.generateKeyPair();
this.config = {
// Use asymmetric keys for better security
publicKey: config.publicKey || generatedKeyPair.publicKey,
privateKey: config.privateKey || generatedKeyPair.privateKey,
// Token configuration
accessTokenExpiry: config.accessTokenExpiry || '15m',
refreshTokenExpiry: config.refreshTokenExpiry || '7d',
issuer: config.issuer || 'your-api.com',
audience: config.audience || 'your-app.com',
// Security settings
algorithm: 'RS256', // Use RSA for asymmetric encryption
keyRotationInterval: config.keyRotationInterval || 86400000, // 24 hours
maxTokenAge: config.maxTokenAge || 3600000, // 1 hour
// Blacklist configuration
blacklistType: config.blacklistType || 'memory', // 'redis' or 'memory'
redisConfig: config.redisConfig || { host: 'localhost', port: 6379 }
};
this.blacklist = new Map();
this.currentKeyId = this.generateKeyId();
this.keys = new Map([[this.currentKeyId, this.config.publicKey]]);
}
// Generate RSA key pair
generateKeyPair() {
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem'
}
});
return { publicKey, privateKey };
}
// Generate unique key ID
generateKeyId() {
return `key-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
// Rotate keys
rotateKeys() {
const oldKeyId = this.currentKeyId;
const newKeyId = this.generateKeyId();
const newKeyPair = this.generateKeyPair();
this.keys.set(newKeyId, newKeyPair.publicKey);
this.config.privateKey = newKeyPair.privateKey;
this.config.publicKey = newKeyPair.publicKey;
// Keep old keys for 1 hour to validate existing tokens
setTimeout(() => {
this.keys.delete(oldKeyId);
}, 3600000);
this.currentKeyId = newKeyId;
return newKeyId;
}
// Add token to blacklist
async addToBlacklist(token, expiryTime) {
const tokenId = this.getTokenId(token);
const expiry = expiryTime || this.getTokenExpiry(token);
if (this.config.blacklistType === 'redis') {
// Redis implementation for distributed systems
await this.redis.setex(`jwt:blacklist:${tokenId}`, expiry, '1');
} else {
// In-memory blacklist for single instance
this.blacklist.set(tokenId, Date.now() + (expiry * 1000));
}
}
// Check if token is blacklisted
async isBlacklisted(token) {
const tokenId = this.getTokenId(token);
if (this.config.blacklistType === 'redis') {
const result = await this.redis.get(`jwt:blacklist:${tokenId}`);
return !!result;
} else {
const expiry = this.blacklist.get(tokenId);
return expiry && expiry > Date.now();
}
}
// Extract token ID (jti claim)
getTokenId(token) {
const decoded = jwt.decode(token);
return decoded.jti;
}
// Get token expiry
getTokenExpiry(token) {
const decoded = jwt.decode(token);
return decoded.exp - Math.floor(Date.now() / 1000);
}
// Create JWT with enhanced security
async createToken(payload, options = {}) {
const tokenId = crypto.randomBytes(16).toString('hex');
const keyId = this.currentKeyId;
const enhancedPayload = {
...payload,
jti: tokenId, // JWT ID for blacklisting
iat: Math.floor(Date.now() / 1000),
iss: this.config.issuer,
aud: this.config.audience
};
const tokenOptions = {
algorithm: this.config.algorithm,
expiresIn: options.expiresIn || this.config.accessTokenExpiry,
keyid: keyId
};
return jwt.sign(enhancedPayload, this.config.privateKey, tokenOptions);
}
// Verify JWT with enhanced security checks
async verifyToken(token) {
try {
// Check blacklist first
if (await this.isBlacklisted(token)) {
throw new Error('Token has been revoked');
}
// Decode token to get key ID
const decoded = jwt.decode(token, { complete: true });
if (!decoded || !decoded.header || !decoded.header.kid) {
throw new Error('Invalid token structure');
}
const keyId = decoded.header.kid;
// Verify the token hasn't been tampered with
const key = this.keys.get(keyId);
if (!key) {
throw new Error('Invalid key ID');
}
// Verify token signature and claims
const verified = jwt.verify(token, key, {
algorithms: [this.config.algorithm],
issuer: this.config.issuer,
audience: this.config.audience,
maxAge: this.config.maxTokenAge
});
// Additional security checks
if (verified.iat > Math.floor(Date.now() / 1000)) {
throw new Error('Token issued in the future');
}
if (verified.exp - verified.iat > this.config.maxTokenAge / 1000) {
throw new Error('Token validity period exceeds maximum allowed');
}
return verified;
} catch (error) {
console.error('Token verification failed:', error.message);
throw error;
}
}
// Middleware for Express.js
middleware() {
return async (req, res, next) => {
try {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Authorization header required' });
}
const token = authHeader.substring(7);
const decoded = await this.verifyToken(token);
req.user = decoded;
req.token = token;
next();
} catch (error) {
return res.status(401).json({
error: 'Invalid or expired token',
details: error.message
});
}
};
}
// Rate limiting middleware
rateLimitMiddleware(maxAttempts = 5, windowMs = 900000) {
const attempts = new Map();
return async (req, res, next) => {
const ip = req.ip || req.connection.remoteAddress;
const now = Date.now();
if (!attempts.has(ip)) {
attempts.set(ip, []);
}
const userAttempts = attempts.get(ip);
const validAttempts = userAttempts.filter(time => now - time < windowMs);
if (validAttempts.length >= maxAttempts) {
return res.status(429).json({ error: 'Too many attempts' });
}
validAttempts.push(now);
attempts.set(ip, validAttempts);
next();
};
}
}
// Usage Example
const jwtManager = new JWTSecurityManager({
issuer: 'your-api.com',
audience: 'your-app.com',
accessTokenExpiry: '15m',
refreshTokenExpiry: '7d'
});
// Apply to Express app
const express = require('express');
const app = express();
// Security middleware stack
app.use('/api/*', [
jwtManager.rateLimitMiddleware(),
jwtManager.middleware()
]);
// Protected route
app.get('/api/protected', (req, res) => {
res.json({
message: 'Secure access granted',
user: req.user
});
});
// Logout route
app.post('/api/logout', async (req, res) => {
try {
await jwtManager.addToBlacklist(req.token);
res.json({ message: 'Logged out successfully' });
} catch (error) {
res.status(500).json({ error: 'Logout failed' });
}
});
💻 Pruebas JWT javascript
Escribir pruebas unitarias y de integración para funcionalidades JWT
const jwt = require('jsonwebtoken');
const { expect } = require('chai');
const sinon = require('sinon');
const JWTSecurityManager = require('./jwt-security-manager');
describe('JWT Implementation Tests', () => {
let jwtManager;
const testConfig = {
issuer: 'test-api.com',
audience: 'test-app.com',
accessTokenExpiry: '1h',
refreshTokenExpiry: '7d',
algorithm: 'HS256'
};
beforeEach(() => {
jwtManager = new JWTSecurityManager(testConfig);
});
describe('Token Creation', () => {
it('should create a valid JWT token', () => {
const payload = { userId: 123, email: '[email protected]' };
const token = jwtManager.createToken(payload);
expect(token).to.be.a('string');
expect(token.split('.')).to.have.lengthOf(3);
});
it('should include required claims', () => {
const payload = { userId: 123 };
const token = jwtManager.createToken(payload);
const decoded = jwt.decode(token);
expect(decoded).to.have.property('iat');
expect(decoded).to.have.property('iss', testConfig.issuer);
expect(decoded).to.have.property('aud', testConfig.audience);
expect(decoded).to.have.property('jti');
expect(decoded).to.have.property('userId', 123);
});
});
describe('Token Verification', () => {
it('should verify a valid token', async () => {
const payload = { userId: 123, email: '[email protected]' };
const token = jwtManager.createToken(payload);
const verified = await jwtManager.verifyToken(token);
expect(verified).to.have.property('userId', 123);
expect(verified).to.have.property('email', '[email protected]');
});
it('should reject expired tokens', async () => {
const payload = { userId: 123 };
const token = jwtManager.createToken(payload, { expiresIn: '-1s' });
try {
await jwtManager.verifyToken(token);
expect.fail('Should have thrown error for expired token');
} catch (error) {
expect(error.message).to.include('expired');
}
});
it('should reject tokens with invalid signature', async () => {
const payload = { userId: 123 };
const token = jwtManager.createToken(payload);
const tamperedToken = token + 'tampered';
try {
await jwtManager.verifyToken(tamperedToken);
expect.fail('Should have thrown error for invalid signature');
} catch (error) {
expect(error.message).to.include('invalid signature');
}
});
});
describe('Token Blacklisting', () => {
it('should blacklist and reject tokens', async () => {
const payload = { userId: 123 };
const token = jwtManager.createToken(payload);
// Token should be valid initially
let verified = await jwtManager.verifyToken(token);
expect(verified).to.exist;
// Blacklist the token
await jwtManager.addToBlacklist(token);
// Token should now be rejected
try {
await jwtManager.verifyToken(token);
expect.fail('Should have thrown error for blacklisted token');
} catch (error) {
expect(error.message).to.include('revoked');
}
});
});
describe('Middleware Integration', () => {
let req, res, next;
beforeEach(() => {
req = {
headers: {},
ip: '127.0.0.1'
};
res = {
status: sinon.stub().returnsThis(),
json: sinon.stub()
};
next = sinon.stub();
});
it('should pass with valid token', async () => {
const payload = { userId: 123 };
const token = jwtManager.createToken(payload);
req.headers.authorization = `Bearer ${token}`;
const middleware = jwtManager.middleware();
await middleware(req, res, next);
expect(next.calledOnce).to.be.true;
expect(req.user).to.have.property('userId', 123);
});
it('should reject missing authorization header', async () => {
const middleware = jwtManager.middleware();
await middleware(req, res, next);
expect(next.called).to.be.false;
expect(res.status.calledWith(401)).to.be.true;
expect(res.json.calledWith({ error: 'Authorization header required' })).to.be.true;
});
it('should reject invalid token format', async () => {
req.headers.authorization = 'InvalidTokenFormat';
const middleware = jwtManager.middleware();
await middleware(req, res, next);
expect(next.called).to.be.false;
expect(res.status.calledWith(401)).to.be.true;
});
});
describe('Key Rotation', () => {
it('should rotate keys successfully', () => {
const originalKeyId = jwtManager.currentKeyId;
const newKeyId = jwtManager.rotateKeys();
expect(newKeyId).to.not.equal(originalKeyId);
expect(jwtManager.keys.has(originalKeyId)).to.be.true;
expect(jwtManager.keys.has(newKeyId)).to.be.true;
});
it('should verify tokens created with old keys', async () => {
const originalKeyId = jwtManager.currentKeyId;
const payload = { userId: 123 };
const token = jwtManager.createToken(payload);
// Rotate keys
jwtManager.rotateKeys();
// Old token should still be valid
const verified = await jwtManager.verifyToken(token);
expect(verified).to.have.property('userId', 123);
});
});
});
describe('JWT Security Vulnerabilities', () => {
it('should prevent algorithm confusion attacks', async () => {
// Create a token with 'none' algorithm
const maliciousToken = jwt.sign(
{ userId: 'admin', isAdmin: true },
'any-secret',
{ algorithm: 'none' }
);
try {
await jwtManager.verifyToken(maliciousToken);
expect.fail('Should have rejected algorithm none');
} catch (error) {
expect(error.message).to.not.include('admin');
}
});
it('should prevent token replay attacks', async () => {
const payload = { userId: 123 };
const token = jwtManager.createToken(payload);
// First verification should succeed
await jwtManager.verifyToken(token);
// Blacklist the token
await jwtManager.addToBlacklist(token);
// Second verification should fail
try {
await jwtManager.verifyToken(token);
expect.fail('Should have prevented replay attack');
} catch (error) {
expect(error.message).to.include('revoked');
}
});
});
// Performance Tests
describe('JWT Performance', () => {
it('should handle token creation under 10ms', () => {
const payload = { userId: 123, email: '[email protected]' };
const start = Date.now();
for (let i = 0; i < 1000; i++) {
jwtManager.createToken(payload);
}
const duration = Date.now() - start;
const avgTime = duration / 1000;
console.log(`Average token creation time: ${avgTime}ms`);
expect(avgTime).to.be.lessThan(10);
});
it('should handle token verification under 5ms', async () => {
const payload = { userId: 123, email: '[email protected]' };
const token = jwtManager.createToken(payload);
const start = Date.now();
for (let i = 0; i < 1000; i++) {
await jwtManager.verifyToken(token);
}
const duration = Date.now() - start;
const avgTime = duration / 1000;
console.log(`Average token verification time: ${avgTime}ms`);
expect(avgTime).to.be.lessThan(5);
});
});
// Integration Tests
describe('JWT Integration Tests', () => {
let app, server;
before(() => {
const express = require('express');
app = express();
app.use(express.json());
// Apply JWT middleware
app.use('/api/*', jwtManager.middleware());
app.get('/api/test', (req, res) => {
res.json({ user: req.user });
});
server = app.listen(0); // Random available port
});
after(() => {
server.close();
});
it('should integrate with Express.js successfully', async () => {
const payload = { userId: 123, email: '[email protected]' };
const token = jwtManager.createToken(payload);
const response = await fetch(`http://localhost:${server.address().port}/api/test`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
const data = await response.json();
expect(data.user).to.have.property('userId', 123);
});
});