Registry / auth-security / express-jwt-permissions

express-jwt-permissions

JSON →
library1.3.7jsnpmunverified

Express JWT Permissions is an authorization middleware for Node.js applications, designed to work in conjunction with JWT authentication solutions like `express-jwt`. It inspects a decoded JWT token, typically found on `req.user` (or a configurable property), for a permissions array or a space-delimited scope string. The library, currently at stable version 1.3.7, has a moderate release cadence, primarily focusing on security updates, dependency bumps, and TypeScript typing enhancements. Its key differentiator lies in its flexible permission checking logic, supporting simple strings, arrays for AND logic, and nested arrays for complex OR logic combinations of permissions. It also provides configurable options for `requestProperty` and `permissionsProperty` to accommodate diverse JWT payload structures, moving beyond the default `req.user.permissions` pattern, and facilitates custom error handling for permission denials.

npm install express-jwt-permissions
INSTALL
IMPORT
SIG · EXPRESS-JWT-PERMIS
E
express-jwt-permissions
auth-securityjavascriptv1.3.7
Install
—
Import
—
Disk
—
Pass rate
0/ 6
Env Coverage0 / 6
glibc
18–22
musl
18–22
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18–226 runs
build_error
glibc
node 18–226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

guardFactory
✓ import guardFactory from 'express-jwt-permissions';
✗ import { guardFactory } from 'express-jwt-permissions';
The primary export is a factory function, typically imported as a default.
GuardOptions
✓ import { GuardOptions } from 'express-jwt-permissions';
✗ import GuardOptions from 'express-jwt-permissions';
TypeScript type for configuration options.
require
✓ const guardFactory = require('express-jwt-permissions');
✗ const { guardFactory } = require('express-jwt-permissions');
CommonJS require for the default factory function. The guard instance is then created via `const guard = guardFactory();`

This quickstart demonstrates how to set up `express-jwt-permissions` with Express.js, including a mock `express-jwt` middleware, configurable permission checking, and a global error handler for `permission_denied` errors. It shows single, array (AND), and nested array (OR) permission logic.

import express from 'express'; import { expressjwt as jwt } from 'express-jwt'; import guardFactory, { GuardOptions } from 'express-jwt-permissions'; const app = express(); const PORT = 3000; // IMPORTANT: Replace 'YOUR_JWT_SECRET' with a strong secret from environment variables // This mock JWT middleware simulates express-jwt's behavior. const mockJwtMiddleware = jwt({ secret: process.env.JWT_SECRET || 'supersecretjwtkeythatshouldbemorecomplex', algorithms: ['HS256'], requestProperty: 'auth', // Where the decoded JWT payload will be placed (e.g., req.auth) getToken: (req) => { if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') { return req.headers.authorization.split(' ')[1]; } return null; } }).unless({ path: ['/public'] }); // Example: allow /public without a token app.use(mockJwtMiddleware); // Initialize the permission guard, configuring it to look for permissions // within the 'auth' property on the request object and specifically in a 'scope' field. const guard = guardFactory({ requestProperty: 'auth', permissionsProperty: 'scope' } as GuardOptions); // Public route, accessible without any specific permissions app.get('/public', (req, res) => { res.send('Welcome to the public area!'); }); // Route requiring 'user:read' permission app.get('/user/profile', guard.check('user:read'), (req, res) => { res.send(`User profile for ${req.auth?.sub || 'unknown'}. Access granted with user:read.`); }); // Route requiring 'admin' OR ('user:write' AND 'user:delete') permissions app.post('/admin/manage', guard.check([ ['admin'], ['user:write', 'user:delete'] ]), (req, res) => { res.send(`Admin management area. User ${req.auth?.sub || 'unknown'} has required permissions.`); }); // Global error handler for permission_denied errors app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => { if (err.code === 'permission_denied') { console.error('Permission denied:', err.message); return res.status(403).send('Forbidden: Insufficient permissions.'); } next(err); // Pass other errors to the next error handler }); app.listen(PORT, () => { console.log(`Server running on http://localhost:${PORT}`); console.log('Test with valid JWTs in Authorization: Bearer <token>'); console.log('e.g., token with payload { "sub": "user1", "scope": "user:read" }'); console.log('e.g., token with payload { "sub": "admin1", "scope": "admin user:write user:delete" }'); });
Debug
Known issues
breakingBeginning with v1.3.7, `express-jwt-permissions` upgraded its internal `express-unless` dependency to v2. While the primary impact was internal typings, users indirectly relying on `express-unless`'s API or sensitive to transitive major version bumps should review the `express-unless` v2 changelog for potential breaking changes in their specific use cases.
fix
Ensure compatibility by testing your application with `express-jwt-permissions@1.3.7`. Direct code changes within `express-jwt-permissions` usage are typically not required, but verify `express-unless` v2 changes do not impact your specific environment or deeper integrations.
affects: >=1.3.7
gotcha`express-jwt-permissions` *must* be used after a JWT authentication middleware (e.g., `express-jwt`) that successfully decodes the token and attaches the payload to `req.user` (or a configured `requestProperty`). Without a decoded token on the request object, permission checks will always fail.
fix
Ensure `express-jwt` or a similar JWT decoding middleware is applied *before* any `express-jwt-permissions` middleware. Configure `express-jwt-permissions`'s `requestProperty` if your JWT middleware uses a different property than `req.user` (e.g., `req.auth`).
affects: >=1.0.0
gotchaBy default, the middleware expects permissions to be an array or string at `req.user.permissions`. If your decoded JWT token stores permissions in a different location (e.g., `req.auth.scope` or `req.identity.roles`), you *must* configure `requestProperty` and `permissionsProperty` when initializing the guard.
fix
Initialize the guard with appropriate configuration options: `const guard = require('express-jwt-permissions')({ requestProperty: 'identity', permissionsProperty: 'scope' });` to match your JWT payload structure.
affects: >=1.0.0
gotchaWhen a permission check fails, `express-jwt-permissions` throws an error with `err.code === 'permission_denied'`. If this error is not explicitly caught and handled by a custom Express error middleware, it can lead to an unhandled error, a generic 500 status, or unintended application behavior.
fix
Implement a dedicated error handling middleware *after* all routes and `express-jwt-permissions` checks: `app.use(function (err, req, res, next) { if (err.code === 'permission_denied') { res.status(403).send('Forbidden'); } next(err); });`
affects: >=1.0.0
deprecatedPrior to v1.3.2, TypeScript projects with `esModuleInterop: false` in `tsconfig.json` might have encountered issues with typings for `express-jwt-permissions` due to how default imports were handled, potentially leading to compilation errors or incorrect type inference.
fix
Upgrade to `express-jwt-permissions@1.3.2` or higher to resolve typing compatibility issues, or ensure `esModuleInterop: true` is set in your `tsconfig.json` for older versions.
affects: <1.3.2
Errors
Common errors & fixes
UnhandledPromiseRejectionWarning: Error: permission_denied
A permission check failed, and no Express error handling middleware was defined to catch the `permission_denied` error.
fix
Implement a global Express error handler (after all routes) to specifically catch errors where `err.code === 'permission_denied'` and respond with an appropriate status (e.g., 403 Forbidden).
TypeError: Cannot read properties of undefined (reading 'permissions')
The `requestProperty` or `permissionsProperty` options are misconfigured, or the JWT authentication middleware failed to attach a decoded token to the request object, meaning `req.user` (or `req.auth`, etc.) or its `permissions` field is missing.
fix
Verify that a JWT authentication middleware is running correctly *before* `express-jwt-permissions`. Ensure `guardFactory` is configured with `requestProperty` and `permissionsProperty` to match the actual location of permissions in your decoded JWT payload.
TypeError: guard.check is not a function
The `express-jwt-permissions` module was imported or required incorrectly, failing to instantiate the guard factory function. For example, using `require('express-jwt-permissions').check` directly.
fix
Ensure the guard factory is called to create an instance: `const guardFactory = require('express-jwt-permissions'); const guard = guardFactory();` or `import guardFactory from 'express-jwt-permissions'; const guard = guardFactory();`
Property 'permissions' does not exist on type 'Request<ParamsDictionary, any, any, Query, Record<string, any>>'.
When using TypeScript, the `Request` type does not inherently know about the properties added by `express-jwt` (like `req.user` or `req.auth`) or `express-jwt-permissions`.
fix
Augment the `express` Request type in a declaration file (e.g., `src/types/express.d.ts`): `declare namespace Express { interface Request { user?: { permissions?: string[] | string; [key: string]: any; }; auth?: { scope?: string | string[]; [key: string]: any; }; } }`. Adjust `user` to your `requestProperty` and `permissions` to your `permissionsProperty`.
Upgrade
Version history
1.3.7latest on npm
Audit
Dependencies
express-unlessrequiredProvides conditional middleware execution, allowing routes to bypass permission checks. Upgraded to v2 in express-jwt-permissions v1.3.7.
express-jwtoptionalThis package is designed to be used after `express-jwt` (or similar middleware) has decoded a JWT and attached its payload to the request object. It's a conceptual, not a direct runtime, dependency.
Agent activity
25 hits · last 30 days
node
20
Amazon
1
OpenAI (training)
1
Resources