JSON Web Token implementation for Node.js supporting both symmetric and asymmetric cryptographic algorithms
npx @tessl/cli install tessl/npm-jsonwebtoken@9.0.0A comprehensive JSON Web Token (JWT) implementation for Node.js providing secure token creation, verification, and decoding with support for both symmetric (HMAC) and asymmetric (RSA, ECDSA) cryptographic algorithms.
npm install jsonwebtokenconst jwt = require('jsonwebtoken');
const { sign, verify, decode, JsonWebTokenError, TokenExpiredError, NotBeforeError } = require('jsonwebtoken');For ES modules:
import jwt from 'jsonwebtoken';
import { sign, verify, decode, JsonWebTokenError, TokenExpiredError, NotBeforeError } from 'jsonwebtoken';const jwt = require('jsonwebtoken');
// Sign a token with HMAC
const token = jwt.sign({ userId: 123, username: 'alice' }, 'your-secret-key', {
expiresIn: '1h'
});
// Verify a token
try {
const decoded = jwt.verify(token, 'your-secret-key');
console.log(decoded); // { userId: 123, username: 'alice', iat: ..., exp: ... }
} catch (err) {
if (err instanceof jwt.TokenExpiredError) {
console.log('Token expired');
} else {
console.log('Invalid token');
}
}
// Decode without verification (unsafe for untrusted tokens)
const payload = jwt.decode(token);The jsonwebtoken library is built around three core operations:
The library supports all standard JWT algorithms including HMAC (HS256/384/512), RSA (RS256/384/512, PS256/384/512), and ECDSA (ES256/384/512).
Creates and signs JWT tokens with configurable options and claims.
/**
* Signs a JWT token with the provided payload and secret/key
* @param payload - Object literal, buffer, or string representing valid JSON
* @param secretOrPrivateKey - Secret string, buffer, object, or KeyObject for signing
* @param options - Optional signing configuration
* @param callback - Optional callback for asynchronous operation
* @returns JWT string (sync) or calls callback with JWT (async)
*/
function sign(payload: any, secretOrPrivateKey: string | Buffer | object | KeyObject, options?: SignOptions, callback?: SignCallback): string;
interface SignOptions {
algorithm?: Algorithm;
expiresIn?: string | number;
notBefore?: string | number;
audience?: string | string[];
issuer?: string;
jwtid?: string;
subject?: string;
noTimestamp?: boolean;
header?: object;
keyid?: string;
mutatePayload?: boolean;
allowInsecureKeySizes?: boolean;
allowInvalidAsymmetricKeyTypes?: boolean;
encoding?: string;
}
type Algorithm =
| 'HS256' | 'HS384' | 'HS512'
| 'RS256' | 'RS384' | 'RS512'
| 'PS256' | 'PS384' | 'PS512'
| 'ES256' | 'ES384' | 'ES512'
| 'none';
type SignCallback = (err: Error | null, token?: string) => void;Usage Examples:
// Synchronous signing with HMAC
const token = jwt.sign({ foo: 'bar' }, 'secret', { expiresIn: '1h' });
// Asynchronous signing
jwt.sign({ foo: 'bar' }, 'secret', { expiresIn: '1h' }, (err, token) => {
if (err) throw err;
console.log(token);
});
// RSA signing
const fs = require('fs');
const privateKey = fs.readFileSync('private.key');
const token = jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256' });
// Custom claims
const token = jwt.sign(
{ userId: 123 },
'secret',
{
expiresIn: '24h',
audience: 'my-app',
issuer: 'my-service',
subject: 'user-auth'
}
);Verifies JWT tokens with comprehensive security validation.
/**
* Verifies a JWT token and returns the decoded payload
* @param token - JWT string to verify
* @param secretOrPublicKey - Secret/key for verification or callback function
* @param options - Optional verification configuration
* @param callback - Optional callback for asynchronous operation
* @returns Decoded payload (sync) or calls callback with payload (async)
*/
function verify(token: string, secretOrPublicKey: string | Buffer | KeyObject | GetPublicKeyCallback, options?: VerifyOptions, callback?: VerifyCallback): any;
interface VerifyOptions {
algorithms?: Algorithm[];
audience?: string | RegExp | (string | RegExp)[];
complete?: boolean;
issuer?: string | string[];
jwtid?: string;
ignoreExpiration?: boolean;
ignoreNotBefore?: boolean;
subject?: string;
clockTolerance?: number;
maxAge?: string | number;
clockTimestamp?: number;
nonce?: string;
allowInvalidAsymmetricKeyTypes?: boolean;
}
type GetPublicKeyCallback = (header: JwtHeader, callback: (err: any, key?: string | Buffer | KeyObject) => void) => void;
type VerifyCallback = (err: Error | null, payload?: any) => void;
interface JwtHeader {
alg: Algorithm;
typ?: string;
kid?: string;
}Usage Examples:
// Basic verification
const decoded = jwt.verify(token, 'secret');
// Async verification with error handling
jwt.verify(token, 'secret', (err, decoded) => {
if (err) {
if (err instanceof jwt.TokenExpiredError) {
console.log('Token expired at:', err.expiredAt);
} else if (err instanceof jwt.NotBeforeError) {
console.log('Token not active until:', err.date);
} else {
console.log('Token invalid:', err.message);
}
} else {
console.log('Valid token:', decoded);
}
});
// Verification with audience check
const decoded = jwt.verify(token, 'secret', {
audience: 'my-app',
issuer: 'my-service'
});
// Dynamic key resolution
function getKey(header, callback) {
// Fetch key based on header.kid
const key = getPublicKeyFromSomewhere(header.kid);
callback(null, key);
}
jwt.verify(token, getKey, (err, decoded) => {
console.log(decoded);
});
// Complete token information
const result = jwt.verify(token, 'secret', { complete: true });
// result = { header: {...}, payload: {...}, signature: "..." }Decodes JWT tokens without cryptographic verification.
/**
* Decodes a JWT token without verifying the signature (unsafe for untrusted tokens)
* @param token - JWT string to decode
* @param options - Optional decoding configuration
* @returns Decoded payload object or null if invalid
*/
function decode(token: string, options?: DecodeOptions): any | null;
interface DecodeOptions {
complete?: boolean;
json?: boolean;
}Usage Examples:
// Basic decoding
const payload = jwt.decode(token);
// Complete token structure
const decoded = jwt.decode(token, { complete: true });
// decoded = { header: {...}, payload: {...}, signature: "..." }
// Force JSON parsing
const payload = jwt.decode(token, { json: true });Specialized error classes for different JWT validation failures.
/**
* Base error class for JWT-related errors
*/
class JsonWebTokenError extends Error {
name: 'JsonWebTokenError';
message: string;
inner?: Error;
}
/**
* Error thrown when a token has expired
*/
class TokenExpiredError extends JsonWebTokenError {
name: 'TokenExpiredError';
message: 'jwt expired';
expiredAt: Date;
}
/**
* Error thrown when a token is not yet active (nbf claim)
*/
class NotBeforeError extends JsonWebTokenError {
name: 'NotBeforeError';
message: 'jwt not active';
date: Date;
}Common Error Messages:
JsonWebTokenError: 'invalid token', 'jwt malformed', 'jwt signature is required', 'invalid signature'JsonWebTokenError: 'jwt audience invalid', 'jwt issuer invalid', 'jwt id invalid', 'jwt subject invalid'TokenExpiredError: 'jwt expired'NotBeforeError: 'jwt not active'// Supported cryptographic algorithms
type Algorithm =
| 'HS256' | 'HS384' | 'HS512' // HMAC with SHA
| 'RS256' | 'RS384' | 'RS512' // RSASSA-PKCS1-v1_5 with SHA
| 'PS256' | 'PS384' | 'PS512' // RSASSA-PSS with SHA (Node.js 6.12+ or 8+)
| 'ES256' | 'ES384' | 'ES512' // ECDSA with SHA
| 'none'; // No signature
// Standard JWT header structure
interface JwtHeader {
alg: Algorithm;
typ?: 'JWT';
kid?: string; // Key ID
}
// Complete JWT structure when using decode({ complete: true })
interface CompleteJwt {
header: JwtHeader;
payload: any;
signature: string;
}
// Validation result when using verify({ complete: true })
interface CompleteVerifyResult {
header: JwtHeader;
payload: any;
signature: string;
}allowInsecureKeySizes)none algorithm requires explicit inclusion in algorithms array for verificationexp (expiration), nbf (not before), and iat (issued at) claimsmaxAge option for additional age-based validation// Specify allowed algorithms explicitly
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'],
audience: 'my-app',
issuer: 'trusted-issuer'
});
// Use asymmetric algorithms for distributed systems
const token = jwt.sign(payload, privateKey, {
algorithm: 'RS256',
expiresIn: '15m',
audience: 'api-client',
issuer: 'auth-service'
});
// Handle errors appropriately
try {
const decoded = jwt.verify(token, secret);
// Process valid token
} catch (err) {
if (err instanceof jwt.TokenExpiredError) {
// Handle expired token (maybe refresh)
} else if (err instanceof jwt.JsonWebTokenError) {
// Handle invalid token
}
}