In this lesson, you will learn how to implement granular access control by combining Role-Based Access Control (RBAC) with resource ownership checks.
Beyond Simple Roles
While RBAC allows you to define what a user "is" (e.g., admin, editor, viewer), it often isn't enough on its own. For example, an editor should be able to update their own articles, but they shouldn't be able to edit articles written by others. To handle this, we use Ownership-based Authorization.
The Hybrid Middleware Approach
We implement this by creating middleware that evaluates the user's role and then checks if the resource being accessed belongs to that user. Here is how we verify both:
const authorize = (role, checkOwnership = false) => {
return async (req, res, next) => {
// 1. RBAC check
if (req.user.role !== role && req.user.role !== 'admin') {
return next(new Error('Forbidden: Insufficient role'));
}
// 2. Resource ownership check
if (checkOwnership) {
const resource = await db.find(req.params.id);
if (resource.ownerId !== req.user.id) {
return next(new Error('Forbidden: You do not own this resource'));
}
}
next();
};
};
// Usage: Only the author or an admin can update
app.patch('/posts/:id', authorize('editor', true), updatePost);
Why This Architecture Works
By keeping this logic in middleware, you decouple your business logic from security enforcement. The controller (updatePost) remains "clean" because it assumes the request has already been validated. If the user isn't authorized, the middleware triggers your centralized error handler—which you learned about in previous lessons—ensuring consistent responses across your API.
When implementing this, always ensure your req.user object is populated by your authentication middleware before this logic runs. By layering roles (RBAC) with identity checks (Ownership), you create a robust security gate that prevents horizontal privilege escalation, ensuring users can only interact with data they are authorized to manage.
Key Takeaway: Effective authorization uses RBAC to define broad permissions and ownership checks to enforce granular, resource-level security.