11 Authorization Middleware
title: Authorization Middleware in Node.js REST APIs weight: 21 date: 2026-06-28 lastmod: 2026-06-28 description: Learn role-based and permission-based authorization middleware in Node.js REST APIs for controlling access to endpoints based on user roles and resource ownership. tags: [api-development, nodejs]
Authorization middleware in Node.js REST APIs controls access to endpoints by checking user roles, permissions, and resource ownership after authentication, ensuring users can only perform allowed actions.
```mermaid
flowchart TD
A[Authenticated Request] --> B{Auth Middleware}
B -->|Has role admin| C[Allow Access]
B -->|Is resource owner| C
B -->|No permission| D[403 Forbidden]
B -->|Not authenticated| E[401 Unauthorized]
style A fill:#e1f5fe
style B fill:#fff9c4
style C fill:#c8e6c9
style D fill:#ffcdd2
Authorization checks happen after authentication. Two common patterns: role-based access control (RBAC) checks if the user has the required role, and resource-based access control checks if the user owns the resource being accessed. Middleware functions can be chained.
Think of authorization like different employee badges in a building. Authentication proves you are an employee (Anyone with a badge). Authorization determines which floors you can access (RBAC: admin gets all floors, regular employee gets only theirs).
Example: Role-Based Authorization
const authorize = (...allowedRoles) => {
return (req, res, next) => {
if (!req.user) {
return res.status(401).json({ error: 'Authentication required' });
}
if (!allowedRoles.includes(req.user.role)) {
return res.status(403).json({
error: 'Insufficient permissions',
required: allowedRoles,
yourRole: req.user.role
});
}
next();
};
};
// Usage
app.delete('/api/users/:id',
authenticate,
authorize('admin'),
userController.deleteUser
);
app.get('/api/users',
authenticate,
authorize('admin', 'editor'),
userController.listUsers
);
Example: Resource Ownership Authorization
const authorizeOwner = (resourceGetter) => {
return async (req, res, next) => {
try {
const resource = await resourceGetter(req);
if (!resource) {
return res.status(404).json({ error: 'Resource not found' });
}
// Admin can access any resource
if (req.user.role === 'admin') {
req.resource = resource;
return next();
}
// Check ownership
if (resource.userId !== req.user.userId) {
return res.status(403).json({
error: 'You do not own this resource'
});
}
req.resource = resource;
next();
} catch (error) {
next(error);
}
};
};
// Usage
app.patch('/api/orders/:id',
authenticate,
authorizeOwner((req) => findOrder(req.params.id)),
orderController.updateOrder
);
Example: Permission-Based Authorization
// Permission definitions
const permissions = {
'user:read': ['admin', 'editor', 'viewer'],
'user:write': ['admin', 'editor'],
'user:delete': ['admin'],
'order:read': ['admin', 'editor', 'viewer'],
'order:write': ['admin', 'editor'],
'user:read:own': ['*'] // All authenticated users
};
const hasPermission = (permission) => {
return (req, res, next) => {
const allowedRoles = permissions[permission];
if (!allowedRoles) {
return res.status(500).json({ error: 'Undefined permission' });
}
// * means all authenticated users
if (allowedRoles.includes('*')) {
return next();
}
if (!allowedRoles.includes(req.user.role)) {
return res.status(403).json({
error: 'Missing permission',
required: permission
});
}
next();
};
};
// Usage
router.post('/users', hasPermission('user:write'), userController.createUser);
router.delete('/users/:id', hasPermission('user:delete'), userController.deleteUser);
Common Mistakes
- Confusing authentication with authorization — Authentication verifies identity. Authorization verifies permissions. Both are needed but are separate concerns.
- Checking roles without resource ownership — A user with role editor should not edit other users' orders. Check both role and ownership.
- Hard-coding user IDs from tokens — Always verify the user from the token matches the resource owner. Never trust user IDs from request bodies.
- Not handling the 403 vs 401 distinction — 401 means unauthenticated (not logged in). 403 means authenticated but not permitted. Using the wrong code confuses clients.
- Insufficient test coverage for authorization — Test every authorization rule with users of each role, unauthenticated users, and resource owners vs non-owners.
Practice Questions
- What is the difference between 401 and 403 status codes?
- How do you implement resource-based authorization?
- What is RBAC and how does it work?
- Why should authorization be middleware rather than inline checks?
- Challenge: Build an authorization system that combines role-based and resource-based checks. Include admin override, ownership verification, and permission-based access. Test with a blog API where authors can edit their own posts and admins can edit any post.
FAQ
Mini Project
Build a complete authorization system for a blog API. Implement role-based access (admin, editor, author, viewer), resource ownership (authors edit own posts), and permission-based checks. Apply to endpoints: create/edit/delete posts, moderate comments, manage users.
What's Next
Now learn about database integration with Mongoose and Prisma in Building REST APIs with Node.js.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro