Protected Routes and Role-Based Access Guards0%

Protected Routes and Role-Based Access Guards

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Protected Routes and Role-Based Access Guards

1. Client-Side Security & Access Control

In enterprise portals (learning management systems, corporate intranets, financial dashboards), certain views must be restricted based on user authentication and permissions:

  • Guest users should only access /login, /register, and public catalog pages.
  • Authenticated students can access /dashboard and enrolled courses.
  • Only users with the admin role can access /admin/console and /admin/billing.

While true security must always be enforced on the backend server (validating JWT tokens on API calls), client-side route guards are essential to provide a seamless user experience, preventing unauthorized users from accessing restricted layouts.

Output
Route Request: /admin/analytics
│
▼
[Protected Route Guard]
├─ Not Authenticated? ──► Redirect to /login with state: { from: location }
├─ Wrong Role (Student)? ──► Redirect to /unauthorized (HTTP 403 screen)
└─ Authorized (Admin)? ──► Render <Outlet /> (Access Granted!)

2. Implementing an Authentication Guard (<ProtectedRoute>)

In React Router v6, route guards are implemented as wrapper layout components that render an <Outlet /> if authorized, or <Navigate /> if denied:

JSX
// src/components/ProtectedRoute.jsx
import React from 'react';
import { Navigate, Outlet, useLocation } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
 
export default function ProtectedRoute({ allowedRoles }) {
const { user, isAuthenticated, loading } = useAuth();
const location = useLocation();
 
// 1. Show spinner while verifying stored session
if (loading) {
return <div className="loading-screen">Authenticating session...</div>;
}
 
// 2. Unauthenticated: Redirect to login, preserving intended destination!
if (!isAuthenticated) {
return <Navigate to="/login" state={{ from: location }} replace />;
}
 
// 3. Role-Based Access Control (RBAC) check
if (allowedRoles && !allowedRoles.includes(user.role)) {
return <Navigate to="/unauthorized" replace />;
}
 
// 4. Authorized: Render matching child route!
return <Outlet />;
}

3. Configuring Protected Routes in the Route Tree

Using layout wrapping, protecting an entire section of your application requires nesting child routes beneath the guard:

JSX
// src/App.jsx
import { Routes, Route } from 'react-router-dom';
import ProtectedRoute from './components/ProtectedRoute';
import PublicLayout from './layouts/PublicLayout';
import StudentDashboard from './pages/StudentDashboard';
import AdminConsole from './pages/AdminConsole';
import LoginPage from './pages/LoginPage';
import UnauthorizedPage from './pages/UnauthorizedPage';
 
export default function App() {
return (
<Routes>
{/* Public Routes */}
<Route path="/" element={<PublicLayout />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/unauthorized" element={<UnauthorizedPage />} />
 
{/* Authenticated Routes (Students & Admins) */}
<Route element={<ProtectedRoute />}>
<Route path="/dashboard" element={<StudentDashboard />} />
<Route path="/profile" element={<StudentProfile />} />
</Route>
 
{/* Restricted Admin Routes (Admins Only!) */}
<Route element={<ProtectedRoute allowedRoles={['admin', 'superadmin']} />}>
<Route path="/admin" element={<AdminConsole />} />
<Route path="/admin/billing" element={<AdminBilling />} />
</Route>
</Routes>
);
}

4. Returning Users to Their Intended Destination After Login

Notice line 16: <Navigate to="/login" state={{ from: location }} replace />.

When an unauthorized user attempts to visit /admin/billing, the guard stores the attempted URL in navigation state.

Inside the LoginPage component:

JSX
const location = useLocation();
const navigate = useNavigate();
 
// After successful login:
const destination = location.state?.from?.pathname || '/dashboard';
navigate(destination, { replace: true });

The user is seamlessly redirected right back to the page they were originally trying to access!


Interactive Quiz

Practice Quiz

Question 1
What is the primary role of a client-side Protected Route in React Router?
Question 2
What component does React Router v6 use to redirect users declaratively?
Question 3
Why is state={{ from: location }} passed when redirecting an unauthenticated user to /login?
Question 4
If an authorized user passes the permission check in <ProtectedRoute>, what does the guard render?
Question 5
Can client-side route guards replace backend API authorization?
Next Lesson

Scroll Restoration and Optimistic Route Transitions

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext