Mean 15 Authorization
title: "Authorization — Role-Based Access Control in the MEAN Stack" description: "Implement role-based authorization in the MEAN Stack with Express middleware, user roles, permission checking, and Angular route guards." weight: 25 date: 2026-06-28 lastmod: 2026-06-28 tags: [frameworks, mean]
Authorization controls what authenticated users can do. Role-based access control (RBAC) assigns permissions based on user roles like admin, moderator, and regular user.
What You'll Learn
You will implement role-based authorization with Express middleware for API protection and Angular route guards for frontend protection.
Why It Matters
Authorization prevents users from accessing resources or performing actions they should not. It is essential for multi-user applications with different permission levels.
Real-World Use
Durga Antivirus Pro uses three roles: admin (full access), analyst (can view and update threats), and viewer (read-only). Each API endpoint checks the user's role.
flowchart TD
A[Request] --> B[Auth Middleware]
B --> C[Role Check Middleware]
C --> D{User Role}
D -->|Admin| E[Full Access]
D -->|Moderator| F[Limited Write]
D -->|User| G[Read Only]
D -->|No Role| H[Deny Access]
style B fill:#4a90d9,color:#fff
style C fill:#4a90d9,color:#fff
User Schema with Roles
Add a role field to the user schema.
// backend/models/User.js
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
role: {
type: String,
enum: ['user', 'moderator', 'admin'],
default: 'user'
},
permissions: [{
type: String,
enum: ['read:products', 'create:products', 'update:products', 'delete:products',
'read:users', 'create:users', 'update:users', 'delete:users']
}],
active: { type: Boolean, default: true }
}, { timestamps: true });
Expected output: Users have a role field (user, moderator, admin) and an array of granular permissions.
Role-Based Middleware
Create middleware that checks user roles and permissions.
// backend/middleware/authorize.js
function 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,
current: req.user.role
});
}
next();
};
}
function requirePermission(permission) {
return (req, res, next) => {
if (!req.user) {
return res.status(401).json({ error: 'Authentication required' });
}
if (req.user.role === 'admin') {
return next(); // Admin has all permissions
}
if (!req.user.permissions.includes(permission)) {
return res.status(403).json({
error: 'Missing required permission',
permission
});
}
next();
};
}
module.exports = { authorize, requirePermission };
Expected output: authorize('admin', 'moderator') allows only admin and moderator roles. requirePermission('delete:products') checks granular permissions.
Protecting Routes with Role Middleware
Apply authorization middleware to specific routes.
// backend/routes/adminRoutes.js
const express = require('express');
const router = express.Router();
const { authMiddleware } = require('../middleware/auth');
const { authorize, requirePermission } = require('../middleware/authorize');
// All admin routes require authentication
router.use(authMiddleware);
// Admin-only routes
router.get('/dashboard', authorize('admin'), async (req, res) => {
const stats = await getDashboardStats();
res.json(stats);
});
router.get('/users', authorize('admin', 'moderator'), async (req, res) => {
const users = await User.find().select('-password');
res.json(users);
});
// Permission-based routes
router.delete('/products/:id',
requirePermission('delete:products'),
async (req, res) => {
await Product.findByIdAndDelete(req.params.id);
res.status(204).send();
}
);
router.post('/products',
requirePermission('create:products'),
async (req, res) => {
const product = await Product.create(req.body);
res.status(201).json(product);
}
);
Expected output: Admin dashboard is admin-only. User list is accessible to admin and moderator. Delete requires specific permission.
Angular Route Guards
Protect frontend routes based on user roles.
// src/app/guards/role.guard.ts
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from '../services/auth.service';
export function roleGuard(...allowedRoles: string[]): CanActivateFn {
return () => {
const authService = inject(AuthService);
const router = inject(Router);
const user = authService.getCurrentUser();
if (!user) {
return router.parseUrl('/login');
}
if (!allowedRoles.includes(user.role)) {
return router.parseUrl('/unauthorized');
}
return true;
};
}
// Usage in routes
{
path: 'admin',
loadComponent: () => import('./components/admin/admin.component')
.then(m => m.AdminComponent),
canActivate: [roleGuard('admin')],
title: 'Admin Panel'
},
{
path: 'users',
loadComponent: () => import('./components/user-list/user-list.component')
.then(m => m.UserListComponent),
canActivate: [roleGuard('admin', 'moderator')],
title: 'Users'
}
Expected output: Admin route is only accessible to admin users. Users route is accessible to admin and moderator. Unauthorized users are redirected.
Conditional UI Rendering
Show or hide UI elements based on user roles and permissions.
// In component
export class ProductListComponent {
user$ = this.authService.user$;
constructor(private authService: AuthService) {}
canDelete(): boolean {
const user = this.authService.getCurrentUser();
return user?.role === 'admin' || user?.permissions?.includes('delete:products');
}
}
<!-- Template -->
<div *ngIf="user$ | async as user">
<button *ngIf="user.role === 'admin' || user.permissions.includes('delete:products')"
(click)="deleteProduct(product._id)">
Delete
</button>
</div>
Expected output: Delete buttons only appear for authorized users. The condition checks both role and granular permissions.
Common Mistakes
Checking roles only on the frontend: Frontend checks are cosmetic. Always enforce authorization on the backend.
Hardcoding user IDs for admin checks: Use role-based checks, not hardcoded IDs. The admin role should be in the database.
Not handling the 403 status code in Angular: When the API returns 403, show an unauthorized page instead of a generic error.
Giving all users the admin role by accident: The default role should be 'user'. Only explicitly set 'admin' for authorized users.
Not excluding admin from permission checks: Admin should have all permissions. Check for admin role before checking granular permissions.
Practice Questions
- What is the difference between authentication and authorization?
Authentication verifies who you are. Authorization verifies what you are allowed to do.
- How do you protect an API route for admin users only?
Use the authorize('admin') middleware after the auth middleware. Non-admin users receive 403.
- How do you protect an Angular route for specific roles?
Use a role guard that checks the user's role from AuthService and redirects unauthorized users.
- What is the purpose of granular permissions?
They provide finer control than roles. A moderator might create products but not delete them.
- How do you handle unauthorized access in the UI?
Conditionally render buttons and links based on the user's role and permissions. Use *ngIf with role checks.
Challenge
Implement a complete authorization system with: three user roles (user, moderator, admin), granular permissions (CRUD per resource), backend middleware for role and permission checks, Angular route guards, and conditional UI rendering.
Frequently Asked Questions
Mini Project
Build an admin panel with three user levels: admin (full access, can manage users), editor (can create and edit posts but not delete), and viewer (can only view). Implement backend authorization and frontend UI hiding.
What's Next
Learn File Upload handling in the MEAN stack.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro