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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs