Implementing Role-Based Authorization in APIs

Implementing Role-Based Authorization in APIs

Last updated: 3/7/2025

1 hour
Medium

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. πŸš€