Implementing Role-Based Authorization in APIs
Implementing Role-Based Authorization in APIs
Last updated: 3/7/2025
Implementing Role-Based Authorization in APIs
π Introduction
In the previous lesson, we learned about Role-Based Access Control (RBAC), where users have roles such as "user" or "admin" that determine what actions they can perform.
In this lesson, we will:
β
Add a role field to users in our API.
β
Create middleware to restrict access based on roles.
β
Protect specific routes so that only admins can perform certain actions.
π 1. Updating the User Model to Include Roles
Modify models/User.js
to include a role
field:
const mongoose = require("mongoose"); 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", "admin"], default: "user" } // Default role is "user" }); module.exports = mongoose.model("User", UserSchema);
β
New users will have a "user" role by default.
β
Admins must be manually assigned in the database.
π 2. Assigning Admin Roles Manually
To make a user an admin, update the role manually in MongoDB:
db.users.updateOne({ email: "admin@example.com" }, { $set: { role: "admin" } })
π 3. Creating Role-Based Authorization Middleware
Create middleware/authorize.js
:
module.exports = function (roles = []) { return (req, res, next) => { if (!roles.includes(req.user.role)) { return res.status(403).json({ error: "Forbidden: You don't have permission to access this resource" }); } next(); }; };
β
Checks if the user has one of the required roles.
β
If unauthorized, returns 403 Forbidden
.
π 4. Protecting Routes with Role-Based Access
Modify routes/users.js
to allow only admins to delete users:
const express = require("express"); const User = require("../models/User"); const authMiddleware = require("../middleware/auth"); const authorize = require("../middleware/authorize"); const router = express.Router(); // Get all users (Admin only) router.get("/", authMiddleware, authorize(["admin"]), async (req, res) => { const users = await User.find(); res.json(users); }); // Delete a user (Admin only) router.delete("/:id", authMiddleware, authorize(["admin"]), async (req, res) => { const user = await User.findById(req.params.id); if (!user) return res.status(404).json({ error: "User not found" }); await user.deleteOne(); res.json({ message: "User deleted successfully" }); }); module.exports = router;
β
Only admins can view all users.
β
Only admins can delete users.
π 5. Testing Role-Based Authorization
β 1οΈβ£ Logging in as a Regular User
POST /auth/login
{ "email": "alice@example.com", "password": "mypassword" }
Response:
{ "token": "eyJhbGciOiJIUzI1NiIs..." }
β 2οΈβ£ Trying to Access Admin Routes as a Regular User
GET /users Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
β Response:
{ "error": "Forbidden: You don't have permission to access this resource" }
β 3οΈβ£ Logging in as an Admin
POST /auth/login
{ "email": "admin@example.com", "password": "adminpassword" }
β 4οΈβ£ Accessing Admin Routes as an Admin
GET /users Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
β Response:
[ { "_id": "656a7f3bc4d91b0012a8d849", "name": "Alice", "email": "alice@example.com", "role": "user" } ]
π― Summary
β
Users now have roles (user
, admin
).
β
Created middleware to enforce role-based authorization.
β
Only admins can access restricted routes.
β Next Lesson: Securing Passwords and Authentication Best Practices
In the next lesson, weβll focus on password security, preventing brute force attacks, and improving authentication security. π