Lesson 28 — Role-Based Access Control (RBAC) in React (Production-Ready)

🧭 Introduction

In the previous lesson, you learned who the user is (authentication).

Now comes the next critical question:

What is the user allowed to do?

Not every user should:

  • Access every page
  • See every button
  • Perform every action

That’s where Role-Based Access Control (RBAC) comes in.

RBAC is a must-have concept for:

  • Admin panels
  • Dashboards
  • SaaS products
  • Enterprise applications

This lesson teaches you how professional React applications design and enforce RBAC cleanly and securely.


🎯 What You’ll Learn in This Lesson

By the end of this lesson, you will understand:

  • What RBAC really means
  • Common RBAC models
  • Where RBAC logic should live
  • Implementing RBAC in React
  • Protecting routes, components, and actions
  • Common mistakes to avoid

🧠 What Is Role-Based Access Control (RBAC)?

RBAC means:

Access is granted based on user roles.

Examples of roles:

  • admin
  • manager
  • editor
  • user
  • viewer

Each role has specific permissions.


🧩 Authentication vs Authorization (Quick Recap)

ConceptQuestion
AuthenticationWho are you?
Authorization (RBAC)What can you do?

RBAC is a form of authorization.


🏗️ Typical RBAC Architecture

A clean RBAC system looks like this:

Backend → Sends user role
Frontend → Stores role securely
RBAC Layer → Decides access
UI → Shows / hides features

Important rule:

🔐 Frontend RBAC is for UX — backend RBAC is for security


🧠 Where Should RBAC Logic Live?

❌ Inside individual components
❌ Scattered if (role === "admin") everywhere

✅ Centralized authorization layer

Usually inside:

  • Auth Context
  • Permission utility functions

🧩 Storing Role in Auth Context

const AuthContext = React.createContext();

function AuthProvider({ children }) {
  const [user, setUser] = React.useState(null);

  const login = (userData) => {
    setUser(userData); // includes role
  };

  return (
    <AuthContext.Provider value={{ user }}>
      {children}
    </AuthContext.Provider>
  );
}

Example user object:

{
  id: 1,
  name: "Avni",
  role: "admin"
}


🔐 Route-Level RBAC (Protected Routes)

Role-Based Protected Route

function RoleProtectedRoute({ allowedRoles, children }) {
  const { user } = useAuth();

  if (!user) {
    return <Navigate to="/login" />;
  }

  if (!allowedRoles.includes(user.role)) {
    return <Navigate to="/unauthorized" />;
  }

  return children;
}


Usage

<RoleProtectedRoute allowedRoles={["admin"]}>
  <AdminDashboard />
</RoleProtectedRoute>

✔ Clean
✔ Centralized
✔ Scalable


🧠 Component-Level RBAC

Sometimes routes are accessible, but features inside them are not.


Example — Button Access

function DeleteButton() {
  const { user } = useAuth();

  if (user.role !== "admin") return null;

  return <button>Delete User</button>;
}


Cleaner Approach — Permission Wrapper

function Can({ allowedRoles, children }) {
  const { user } = useAuth();

  if (!user || !allowedRoles.includes(user.role)) {
    return null;
  }

  return children;
}


Usage

<Can allowedRoles={["admin", "manager"]}>
  <button>Approve</button>
</Can>

✔ Declarative
✔ Reusable


🧠 RBAC Using Permissions (Advanced)

Instead of roles, use permissions:

const permissions = {
  admin: ["create", "edit", "delete"],
  editor: ["edit"],
  viewer: []
};


Checking Permission

function hasPermission(user, permission) {
  return permissions[user.role]?.includes(permission);
}


Usage

{hasPermission(user, "delete") && <DeleteButton />}

This approach scales better in large systems.


🚨 Important Security Reminder

⚠️ Frontend RBAC is NOT security
⚠️ Backend must enforce access control

Frontend RBAC:

  • Improves UX
  • Prevents accidental actions

Backend RBAC:

  • Prevents data breaches

Always enforce RBAC on both sides.


❌ Common RBAC Mistakes

❌ Trusting frontend-only checks

❌ Hardcoding roles everywhere

❌ Not handling unauthorized UI states

❌ Mixing auth and RBAC logic

❌ Forgetting backend enforcement


🧠 Handling Unauthorized Access Gracefully

Create an Unauthorized page:

function Unauthorized() {
  return <h2>🚫 You do not have access to this page</h2>;
}

Redirect users instead of crashing.


🎯 Best Practices (Senior-Level)

✅ Centralize RBAC logic
✅ Use declarative permission checks
✅ Hide UI safely
✅ Always enforce on backend
✅ Design roles carefully
✅ Prefer permissions for large apps


❓ FAQs — RBAC in React

🔹 Is RBAC frontend-only?

No — backend enforcement is mandatory.


🔹 Should I store roles in JWT?

Yes — commonly done.


🔹 Context or Redux for RBAC?

Context is sufficient for most apps.


🔹 Is RBAC asked in interviews?

Yes — especially for system design rounds.


🧠 Quick Recap

✔ RBAC controls what users can do
✔ Roles or permissions define access
✔ Protect routes and components
✔ Centralize authorization logic
✔ Backend enforcement is essential


🎉 Conclusion

RBAC is what turns a simple React app into a secure, enterprise-ready system.

When implemented correctly:

  • UX becomes clearer
  • Security improves
  • Code stays clean
  • Scaling becomes easier

With authentication + RBAC mastered, you now understand how real-world React applications control access 🔐⚛️


👉 Next Section

SECTION 9 — Testing React Applications

👉 Next Lesson

Lesson 29 — Testing Strategy & Philosophy

Leave a Comment