JAVASCRIPT
Securely Verify JSON Web Tokens (JWT) in Node.js
Implement robust JWT verification in Node.js using `jsonwebtoken` to ensure token integrity, check expiration, and validate issuer/audience for secure API authentication.
const jwt = require('jsonwebtoken');
// WARNING: In a real application, SECRET_KEY should be loaded from environment variables
// (e.g., process.env.JWT_SECRET) and NOT hardcoded!
const JWT_SECRET = 'your_super_secret_key_change_me_in_prod';
const JWT_ISSUER = 'your-app-domain.com';
const JWT_AUDIENCE = 'your-api-client-id';
// Function to generate a sample token (for demonstration)
function generateToken(payload, expiresIn = '1h') {
return jwt.sign(payload, JWT_SECRET, {
expiresIn: expiresIn,
issuer: JWT_ISSUER,
audience: JWT_AUDIENCE
});
}
// Function to securely verify a JWT
function verifyToken(token) {
try {
const decoded = jwt.verify(token, JWT_SECRET, {
issuer: JWT_ISSUER,
audience: JWT_AUDIENCE,
algorithms: ['HS256'] // Specify expected algorithm to prevent algorithm confusion attacks
});
console.log('Token verified successfully:', decoded);
return { valid: true, decoded };
} catch (error) {
console.error('JWT Verification Error:', error.message);
if (error instanceof jwt.TokenExpiredError) {
return { valid: false, error: 'Token expired' };
}
if (error instanceof jwt.JsonWebTokenError) {
return { valid: false, error: 'Invalid token' };
}
return { valid: false, error: 'Unknown JWT error' };
}
}
// --- Demonstration ---
const userPayload = { userId: 'abc-123', role: 'admin' };
console.log('--- Generating Valid Token ---');
const validToken = generateToken(userPayload);
console.log('Generated Token:', validToken);
console.log('
--- Verifying Valid Token ---');
let result = verifyToken(validToken);
if (result.valid) {
console.log('Access Granted for user:', result.decoded.userId);
} else {
console.log('Access Denied:', result.error);
}
console.log('
--- Verifying Malformed Token ---');
const malformedToken = validToken + 'malicious_tamper';
result = verifyToken(malformedToken);
if (result.valid) {
console.log('Access Granted (should not happen for malformed token)!');
} else {
console.log('Access Denied (expected for malformed token):', result.error);
}
console.log('
--- Verifying Token with Incorrect Secret ---');
const tokenWithWrongSecret = jwt.sign(userPayload, 'wrong_secret');
result = verifyToken(tokenWithWrongSecret);
if (result.valid) {
console.log('Access Granted (should not happen for wrong secret)!');
} else {
console.log('Access Denied (expected for wrong secret):', result.error);
}
console.log('
--- Verifying Expired Token ---');
const expiredToken = generateToken(userPayload, '1ms'); // Token expires almost immediately
setTimeout(() => {
result = verifyToken(expiredToken);
if (result.valid) {
console.log('Access Granted (should not happen for expired token)!');
} else {
console.log('Access Denied (expected for expired token):', result.error);
}
}, 100); // Wait a bit for the token to expire
How it works: This Node.js snippet illustrates how to securely verify JSON Web Tokens (JWTs) using the `jsonwebtoken` library. Key practices include using a strong, secret key (from environment variables), validating both the issuer and audience claims, explicitly specifying the expected algorithm (`algorithms: ['HS256']`) to prevent "algorithm confusion" attacks, and robust error handling for various verification failures like expiration or invalid signatures.