jwt-middleware-auth
v2.1.5
Published
A comprehensive middleware library for JWT authentication and role-based authorization in Express.js
Downloads
620
Readme
JWT Middleware Auth
A comprehensive middleware library for JWT authentication and role-based authorization in Express.js applications.
Installation
npm install jwt-middleware-authDependencies
This package requires jsonwebtoken:
npm install jsonwebtoken@^9.0.3Usage
Basic Setup
const express = require('express');
const { verifyToken, authorizeRoles } = require('jwt-middleware-auth');
const app = express();
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
// Public route
app.get('/api/public', (req, res) => {
res.json({ message: 'Public data' });
});
// Protected route - requires authentication
app.get('/api/profile', verifyToken(JWT_SECRET), (req, res) => {
res.json({ user: req.user });
});
// Role-based route - requires specific role
app.get('/api/admin', verifyToken(JWT_SECRET), authorizeRoles('admin'), (req, res) => {
res.json({ message: 'Admin data' });
});Token Format
Tokens should be sent in the request header:
token: Bearer <your-jwt-token>Example:
token: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Available Middlewares
Authentication Middlewares
verifyToken(secret)
Verifies JWT token and populates req.user with decoded payload.
app.get('/api/protected', verifyToken(JWT_SECRET), (req, res) => {
// req.user contains: { id, role, email, ... }
res.json({ userId: req.user.id });
});Response on failure:
401- Token not provided or invalid token
Authorization Middlewares
authorizeRoles(...allowedRoles)
Checks if authenticated user has one of the allowed roles. Must be used after verifyToken.
// Single role
app.get('/api/admin-only',
verifyToken(JWT_SECRET),
authorizeRoles('admin'),
controller
);
// Multiple roles
app.get('/api/management',
verifyToken(JWT_SECRET),
### Request Validation Middlewares
#### `validateDashboardLogin`
Validates the dashboard login request body.
**Rules:**
- `role` must NOT be provided
- `email` is required
- `password` is required unless `google` is truthy
```javascript
const express = require('express');
const { validateDashboardLogin } = require('jwt-middleware-auth');
const router = express.Router();
router.post('/dashboard/login', validateDashboardLogin, loginController);Failure behavior:
Returns
400with a JSON{ message }describing the validation error.authorizeRoles('admin', 'manager', 'SuperManager'), controller );
**Response on failure:**
- `401` - User not authenticated
- `403` - User doesn't have required role
**Supported roles:**
- `user` - Regular user
- `admin` - Administrator
- `seller` - Store seller/vendor
- `paymentManager` - Payment processing manager
- `manager` - General manager
- `SuperManager` - Super administrator
---
#### `verifyTokenAndAuthorization(secret)`
Allows access if user is updating their own account OR is an admin.
```javascript
// User can update their own profile, or admin can update any profile
app.put('/api/users/:id',
verifyTokenAndAuthorization(JWT_SECRET),
updateUserController
);Access granted when:
req.user.id === req.params.id(own account)req.user.role === 'admin'(admin override)
verifyAdmin(secret)
Verifies user has admin privileges.
app.delete('/api/users/:id',
verifyAdmin(JWT_SECRET),
deleteUserController
);Access granted when:
req.user.isAdmin === true
verifyManager(secret)
Allows access if user is a manager or accessing their own resource.
app.get('/api/reports/:id',
verifyManager(JWT_SECRET),
getReportController
);Access granted when:
req.user.id == req.params.id(own resource)req.user.role == 'manager'(manager access)
verifySeller(secret)
Allows access if user is a seller, payment manager, or accessing their own resource.
app.get('/api/stores/:id',
verifySeller(JWT_SECRET),
getStoreController
);Access granted when:
req.user.id == req.params.id(own resource)req.user.role == 'seller'(seller access)req.user.role == 'paymentManager'(payment manager access)
verifySellerRole(secret)
Focused role validation for sellers - ideal for resource creation.
app.post('/api/offers',
verifySellerRole(JWT_SECRET),
createOfferController
);Access granted when:
req.user.role === 'seller'req.user.role === 'paymentManager'
verifySellerOrAdmin(secret)
Allows access for sellers, managers, admins, or super managers.
app.get('/api/store/:id/orders',
verifySellerOrAdmin(JWT_SECRET),
getOrdersController
);Access granted when:
req.user.roleis one of:admin,seller,manager,SuperManager
Advanced Middlewares
verifyTokenAndOwnership(secret, getResourceOwnerId)
Higher-order middleware that verifies token and checks resource ownership.
const { verifyTokenAndOwnership } = require('jwt-middleware-auth');
const Offer = require('./models/Offer');
// Define ownership check function
const checkOfferOwnership = async (req) => {
const offer = await Offer.findById(req.params.id);
if (!offer) {
throw new Error('Offer not found');
}
return offer.sellerId; // Return the owner ID
};
// Apply to route
app.put('/api/offers/:id',
verifyTokenAndOwnership(JWT_SECRET, checkOfferOwnership),
updateOfferController
);Parameters:
secret- JWT secret keygetResourceOwnerId- Async function that returns the resource owner's ID
Access granted when:
ownerId === req.user.id(user owns the resource)
Responses:
404- Resource not found403- User doesn't own the resource500- Error during ownership verification
Complete Examples
User Management API
const express = require('express');
const {
verifyToken,
verifyTokenAndAuthorization,
verifyAdmin
} = require('jwt-middleware-auth');
const app = express();
const JWT_SECRET = process.env.JWT_SECRET;
// Get own profile or any profile (admin)
app.get('/api/users/:id',
verifyTokenAndAuthorization(JWT_SECRET),
(req, res) => {
// Fetch and return user
}
);
// Update own profile or any profile (admin)
app.put('/api/users/:id',
verifyTokenAndAuthorization(JWT_SECRET),
(req, res) => {
// Update user
}
);
// Delete user (admin only)
app.delete('/api/users/:id',
verifyAdmin(JWT_SECRET),
(req, res) => {
// Delete user
}
);
// List all users (admin only)
app.get('/api/users',
verifyAdmin(JWT_SECRET),
(req, res) => {
// Return all users
}
);E-commerce Store API
const {
verifyToken,
authorizeRoles,
verifySellerRole,
verifyTokenAndOwnership
} = require('jwt-middleware-auth');
const Store = require('./models/Store');
// Get store ownership
const checkStoreOwnership = async (req) => {
const store = await Store.findById(req.params.id);
if (!store) throw new Error('Store not found');
return store.ownerId;
};
// Create store (seller only)
app.post('/api/stores',
verifySellerRole(JWT_SECRET),
createStoreController
);
// Update own store
app.put('/api/stores/:id',
verifyTokenAndOwnership(JWT_SECRET, checkStoreOwnership),
updateStoreController
);
// View store analytics (seller, manager, admin)
app.get('/api/stores/:id/analytics',
verifyToken(JWT_SECRET),
authorizeRoles('seller', 'manager', 'admin'),
getAnalyticsController
);
// Approve store (admin only)
app.post('/api/stores/:id/approve',
verifyToken(JWT_SECRET),
authorizeRoles('admin'),
approveStoreController
);Multi-Role Management System
const { verifyToken, authorizeRoles } = require('jwt-middleware-auth');
// Dashboard access - multiple roles
app.get('/api/dashboard',
verifyToken(JWT_SECRET),
authorizeRoles('admin', 'manager', 'SuperManager'),
(req, res) => {
res.json({ dashboard: 'data' });
}
);
// Financial reports - restricted roles
app.get('/api/reports/financial',
verifyToken(JWT_SECRET),
authorizeRoles('admin', 'paymentManager', 'SuperManager'),
(req, res) => {
res.json({ reports: 'financial data' });
}
);
// System settings - super admin only
app.put('/api/settings',
verifyToken(JWT_SECRET),
authorizeRoles('SuperManager'),
(req, res) => {
res.json({ message: 'Settings updated' });
}
);Error Responses
All middlewares return consistent error responses:
401 Unauthorized
{
"message": "Token is not provided"
}{
"message": "Invalid Token"
}{
"message": "Authentication required"
}403 Forbidden
{
"message": "You are not authorized"
}{
"message": "Access denied. Insufficient permissions."
}{
"message": "Seller role required"
}{
"message": "You are not authorized to access this resource"
}404 Not Found
{
"message": "Resource not found"
}500 Internal Server Error
{
"message": "Error verifying resource ownership"
}JWT Payload Structure
Your JWT tokens should include:
{
id: 'user-id', // Required for ownership checks
role: 'user', // Required for role-based access
isAdmin: false, // Optional for admin checks
email: '[email protected]', // Optional
// ... other claims
}Best Practices
- Use environment variables for secrets - Never hardcode JWT secrets
- Chain middlewares properly - Always use
verifyTokenbefore authorization middlewares - Choose appropriate middleware - Use specific middlewares (e.g.,
authorizeRoles) over general ones - Handle errors gracefully - Use error middleware to catch and format authentication errors
- Implement token refresh - Consider implementing refresh token mechanism for better security
- Short-lived tokens - Use short expiration times for access tokens
- Validate token payload - Ensure JWT payload contains required fields (id, role)
Security Considerations
- Store JWT secrets securely (environment variables, secret managers)
- Use HTTPS in production to prevent token interception
- Implement token expiration and refresh mechanisms
- Consider token revocation strategy for logout
- Validate and sanitize all user inputs
- Use strong, random secret keys (minimum 32 characters)
- Implement rate limiting on authentication endpoints
- Log authentication failures for security monitoring
Middleware Comparison
| Middleware | Authentication | Authorization | Use Case |
|------------|----------------|---------------|----------|
| verifyToken | ✅ | ❌ | Basic authentication |
| authorizeRoles | ❌* | ✅ | Role-based access |
| verifyTokenAndAuthorization | ✅ | ✅ | Self or admin access |
| verifyAdmin | ✅ | ✅ | Admin-only access |
| verifyManager | ✅ | ✅ | Manager or self access |
| verifySeller | ✅ | ✅ | Seller/payment manager or self |
| verifySellerRole | ✅ | ✅ | Seller role validation |
| verifySellerOrAdmin | ✅ | ✅ | Elevated privileges |
| verifyTokenAndOwnership | ✅ | ✅ | Resource ownership |
*Requires verifyToken to be called first
License
MIT
