Skip to content

API Reference verify

Dylan Keys edited this page Aug 1, 2025 · 1 revision

API Reference: jwt.verify()

Verifies a JSON Web Token string and returns the decoded payload if the signature is valid.

Syntax

jwt.verify(token: string, secretOrPublicKey: Secret | PublicKey | GetPublicKeyOrSecret, options?: VerifyOptions): Promise<JwtPayload | string>

Parameters

token

The JWT string to verify.

secretOrPublicKey

The key used to verify the token signature:

  • String - UTF-8 encoded secret for HMAC algorithms
  • Buffer - Secret for HMAC algorithms
  • KeyObject - Public key for RSA/ECDSA algorithms
  • Function - Async function that returns the key (for dynamic key resolution)

options (optional)

Configuration object with the following properties:

Verification Options

Option Type Description
algorithms string[] List of allowed algorithms
audience string | RegExp | (string|RegExp)[] Expected audience
complete boolean Return an object with decoded header and payload
issuer string | string[] Expected issuer
jwtid string Expected JWT ID
ignoreExpiration boolean Skip expiration check
ignoreNotBefore boolean Skip not-before check
subject string Expected subject
clockTolerance number Clock tolerance in seconds
maxAge string | number Maximum token age
clockTimestamp number Time to use as current time (seconds)
nonce string Expected nonce value
allowInvalidAsymmetricKeyTypes boolean Allow mismatched key types

Return Value

Returns a Promise that resolves to:

  • Decoded payload (default) - The JWT payload as an object or string
  • Complete JWT (when complete: true) - Object with { header, payload, signature }

Examples

Basic Verification

const jwt = require('jsonwebtoken');

try {
  const decoded = await jwt.verify(token, 'secret');
  console.log(decoded); // { userId: 123, iat: 1516239022 }
} catch (err) {
  console.error('Invalid token');
}

RSA Public Key Verification

const fs = require('fs');
const publicKey = fs.readFileSync('public.pem');

try {
  const decoded = await jwt.verify(token, publicKey);
  console.log(decoded);
} catch (err) {
  console.error('Invalid signature');
}

Algorithm Validation

try {
  // Only allow specific algorithms
  const decoded = await jwt.verify(token, publicKey, {
    algorithms: ['RS256', 'RS384']
  });
} catch (err) {
  if (err.message.includes('invalid signature')) {
    console.error('Algorithm mismatch');
  }
}

Audience Validation

// Single audience
const decoded = await jwt.verify(token, secret, {
  audience: 'urn:my-app'
});

// Multiple audiences
const decoded = await jwt.verify(token, secret, {
  audience: ['urn:my-app', 'urn:other-app']
});

// Regex pattern
const decoded = await jwt.verify(token, secret, {
  audience: /^urn:app:.+$/
});

Complete Token Information

const complete = await jwt.verify(token, secret, {
  complete: true
});

console.log(complete.header);    // { alg: 'HS256', typ: 'JWT' }
console.log(complete.payload);   // { userId: 123, ... }
console.log(complete.signature); // 'xyz...'

Dynamic Key Resolution

// Function that returns the appropriate key
async function getKey(header) {
  // Fetch key based on kid (key ID) in header
  const key = await fetchKeyFromDatabase(header.kid);
  return key;
}

try {
  const decoded = await jwt.verify(token, getKey);
  console.log(decoded);
} catch (err) {
  console.error('Verification failed');
}

Using with jwks-rsa

const jwksClient = require('jwks-rsa');

const client = jwksClient({
  jwksUri: 'https://YOUR_DOMAIN/.well-known/jwks.json'
});

async function getKey(header) {
  const key = await client.getSigningKey(header.kid);
  return key.publicKey || key.rsaPublicKey;
}

const decoded = await jwt.verify(token, getKey);

Clock Tolerance

Handle small time differences between servers:

const decoded = await jwt.verify(token, secret, {
  clockTolerance: 60 // 60 seconds tolerance
});

Maximum Age

Reject tokens older than specified age:

const decoded = await jwt.verify(token, secret, {
  maxAge: '2h' // Token must be less than 2 hours old
});

TypeScript Usage

import jwt, { JwtPayload, VerifyOptions, GetPublicKeyOrSecret } from 'jsonwebtoken';

interface TokenPayload extends JwtPayload {
  userId: number;
  role: string;
}

const options: VerifyOptions = {
  algorithms: ['RS256'],
  audience: 'api.example.com',
  issuer: 'auth.example.com'
};

try {
  const decoded = await jwt.verify(token, publicKey, options) as TokenPayload;
  console.log(decoded.userId); // Type-safe access
} catch (error) {
  if (error instanceof jwt.TokenExpiredError) {
    console.log('Token expired at:', error.expiredAt);
  } else if (error instanceof jwt.JsonWebTokenError) {
    console.log('Invalid token:', error.message);
  }
}

Error Handling

The verify method will reject with specific error types:

TokenExpiredError

try {
  const decoded = await jwt.verify(token, secret);
} catch (err) {
  if (err.name === 'TokenExpiredError') {
    console.log('Token expired at:', err.expiredAt);
  }
}

JsonWebTokenError

try {
  const decoded = await jwt.verify(token, secret);
} catch (err) {
  if (err.name === 'JsonWebTokenError') {
    // Could be: invalid signature, jwt malformed, etc.
    console.log('JWT Error:', err.message);
  }
}

NotBeforeError

try {
  const decoded = await jwt.verify(token, secret);
} catch (err) {
  if (err.name === 'NotBeforeError') {
    console.log('Token not active until:', err.date);
  }
}

Security Considerations

  1. Algorithm Validation: Always specify allowed algorithms:

    await jwt.verify(token, key, { algorithms: ['RS256'] });
  2. Audience Validation: Verify the token is for your application:

    await jwt.verify(token, secret, { audience: 'your-app-id' });
  3. Issuer Validation: Verify the token issuer:

    await jwt.verify(token, secret, { issuer: 'trusted-issuer' });
  4. Base64 Secrets: If using base64 encoded secrets:

    const secret = Buffer.from(process.env.JWT_SECRET_BASE64, 'base64');
    const decoded = await jwt.verify(token, secret);

Common Patterns

Express Middleware

async function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];

  if (!token) {
    return res.sendStatus(401);
  }

  try {
    const user = await jwt.verify(token, process.env.ACCESS_TOKEN_SECRET);
    req.user = user;
    next();
  } catch (err) {
    return res.sendStatus(403);
  }
}

Refresh Token Validation

async function validateRefreshToken(token) {
  try {
    const decoded = await jwt.verify(token, process.env.REFRESH_TOKEN_SECRET, {
      audience: 'refresh',
      issuer: 'auth-service'
    });
    return decoded;
  } catch (err) {
    throw new Error('Invalid refresh token');
  }
}

Multi-Tenant Validation

async function verifyTenantToken(token, tenantId) {
  const decoded = await jwt.verify(token, secret, {
    audience: `tenant:${tenantId}`,
    issuer: 'multi-tenant-app'
  });
  return decoded;
}

See Also