express-jwt
raw JSON →Express middleware for validating JWTs (JSON Web Tokens) via the jsonwebtoken library. As of v8.5.1, it supports async secret retrieval, token revocation checks, and a customizable request property (default `req.auth`). It is fully typed (TypeScript) and ESM/CJS compatible. Key differentiators: built-in `.unless()` for path exclusion, optional `credentialsRequired` for public endpoints, and all jsonwebtoken verify options (audience, issuer, clockTolerance, etc.). However, v7→v8 introduced several breaking changes: the exported function is now `expressjwt` (not `jwt`), the request property changed from `req.user` to `req.auth`, and `algorithms` is now required to prevent downgrade attacks. The package is maintained by Auth0 with quarterly releases.
Common errors
error TypeError: jwt is not a function ↓
import { expressjwt as jwt } from 'express-jwt' error Error: secret must be a string or buffer ↓
secret: process.env.JWT_SECRET ?? 'fallback' error Algorithms is not provided ↓
algorithms: ['HS256'] (or your desired algorithm) to the options object. Warnings
breaking v8 changed the exported function from default export `jwt` to named export `expressjwt`. ↓
breaking v8 changed the request property from `req.user` to `req.auth`. ↓
gotcha The `algorithms` option is required; not providing it will throw an error. ↓
gotcha Do not mix symmetric and asymmetric algorithms (e.g., HS256 and RS256) as it can lead to downgrade attacks. ↓
deprecated The `credentialsRequired` option defaulted to `true`; setting to `false` bypasses token validation entirely. ↓
Install
npm install express-jwt yarn add express-jwt pnpm add express-jwt Imports
- expressjwt wrong
import jwt from 'express-jwt'correctimport { expressjwt } from 'express-jwt' - ExpressJwtRequest wrong
import { RequestWithAuth } from 'express-jwt'correctimport { ExpressJwtRequest as RequestWithAuth } from 'express-jwt' - GetVerificationKey wrong
import { GetVerificationKey } from 'express-jwt'correctimport type { GetVerificationKey } from 'express-jwt'
Quickstart
import { expressjwt } from 'express-jwt';
import express from 'express';
const app = express();
// Protected route
app.get(
'/protected',
expressjwt({
secret: process.env.JWT_SECRET ?? 'my-secret',
algorithms: ['HS256'],
}),
(req, res) => {
// Access payload via req.auth
if (!req.auth.admin) return res.sendStatus(401);
res.json({ message: 'Protected data', user: req.auth });
}
);
// Public route
app.get('/token', (req, res) => {
res.send('No auth required');
});
app.listen(3000);