ReviseAlgo Logo

Routing

Protected Routes

Master Protected Routes in React Router, covering authentication guards, declarative redirects using Navigate, and redirect history preservation.

Last Updated: July 15, 2026 12 min read

1. Learning Objectives

In this lesson, you will learn how to restrict page access based on user authorization. By the end of this topic, you will be able to:

  • Differentiate between client-side route guards and server-side security checks.
  • Build custom ProtectedRoute wrapper components.
  • Trigger declarative page redirects using the Navigate element.
  • Preserve the user's target URL path using location states.
  • Integrate user session contexts with the route guard component.

2. Overview

Protected Routes restrict access to authenticated users. React Router handles this by using a custom wrapper component that checks the user's authentication state. If the user is logged in, the component renders the requested child route elements. If not, it redirects the user to the login page using the Navigate component.

3. Why This Topic Matters

Route guards are essential for managing restricted sections in web applications:

  • Information Security: Restricting sensitive pages (like admin dashboards, billing options, or profiles) to authenticated users.
  • Seamless Redirects: Redirecting unauthenticated users to the login page automatically, and returning them to their target page after successful login.

4. Real-World Analogy

Think of protected routes like **a concert VIP section ticket checker**:

  • Unprotected Route (Concert Entrance): Anyone with a general admission ticket can walk in.
  • Protected Route (VIP Lounge Guard): A guard stands at the entrance to the VIP section (the route guard component). If you show a VIP pass (authenticated state), the guard lets you in (renders the route content). If you do not have a pass, the guard redirects you to the ticket counter to upgrade your ticket (redirects to `/login`).

5. Core Concepts

Below is a comparison of Client-Side and Server-Side route protection:

Feature Client-Side Route Protection Server-Side Route Protection
Primary Goal Optimizes user experience by hiding unauthorized views. Protects data by blocking unauthorized API requests.
Security Level Low. Client-side code can be modified by the user. High. Managed on secure servers.
Implementation Uses React state and route wrappers. Uses token validation (JWT) and middleware checks.

6. Syntax & API Reference

This example shows how to build a `ProtectedRoute` wrapper using React Router:

7. Visual Diagram

This diagram displays the flow of user authentication validation during route transitions:

8. Live Example — Full Working Code

Below is a complete HTML page demonstrating a protected dashboard with login, logout, and redirect-back behavior:

What just happened? Clicking the "Dashboard" link while unauthenticated triggers the ProtectedRoute, which redirects you to `/login` using the Navigate component, saving the target path (/dashboard) in the location state. Logging in with a username triggers the login function and redirects you back to the original target path.

9. Interactive Playground

Try It Yourself Challenges:

  1. Add a new public route named "/about", and verify it can be accessed without triggering the login redirect.
  2. Modify ProtectedRoute to accept a list of authorized roles (e.g. `allowedRoles={['admin']}`), and redirect users with a standard 'viewer' role to an "Unauthorized" page.

10. Common Mistakes

Mistake Why it happens Wrong Correct
Relying on client-side route guards for data security Client-side routes can be modified or bypassed by the user. A route guard only optimizes user experience by hiding unauthorized views; actual data security must be enforced on the server. Exposing sensitive APIs on the backend without token authentication. Ensure all backend API routes validate tokens (e.g. JWT) and authorize users on every request, independent of the frontend route guard.
Omitting the replace attribute on login redirects If you redirect unauthenticated users without the replace attribute, the redirect is pushed to the browser's history stack. Clicking the back button in the browser will trigger the redirect again, trapping the user. <Navigate to="/login" /> <Navigate to="/login" replace /> (replaces the current history entry)

11. Best Practices

  • Always validate API requests on the backend: frontend route guards are for user experience; actual data security must be enforced on the server.
  • Use the `replace` attribute on redirects: When redirecting to a login page, use `replace` on the `` component to prevent the redirect from trapping the user in the browser history.
  • Preserve redirect history: Use the location state (`state={{ from: location }}`) to save the user's target URL, and redirect them back to it after successful login.

12. Browser Compatibility/Requirements

Protected routing is supported in all browsers that run React Router.

13. Interview Questions

Q1: Can frontend route guards guarantee the security of sensitive data? Explain your answer.

Answer: No. Frontend route guards only manage the visibility of UI components; they cannot secure data. Since all code running in the browser can be modified or bypassed by the user, frontend security checks can be overridden. Actual data security must be enforced on the backend by validating authentication tokens (e.g. JWT) and user permissions on every API request.

Q2: Why should you use the `replace` attribute on the `` component when redirecting to a login page?

Answer: The `replace` attribute replaces the current entry in the browser's history stack instead of pushing a new one. If you omit `replace` and the user is redirected to `/login`, clicking the back button in their browser will take them back to the protected route. This triggers the redirect again, sending them back to `/login` and trapping them in a loop.

14. Debugging Exercise

Identify the bug in this login redirect logic that traps users in a loop when they click the browser back button:

View Solution

Diagnosis: The Navigate component is missing the replace attribute. This pushes the login redirect onto the browser's history stack, trapping the user in a loop when they click the back button.

Fix: Add the replace attribute to the Navigate component:

15. Practice Exercises

Exercise 1: Create a role-based authorization guard

Build a component named RoleProtectedRoute that accepts an array of allowed roles (e.g. `allowedRoles={['admin', 'editor']}`). Render child components if the user's role matches, or redirect them to an "Unauthorized" page.

16. Scenario-Based Challenge

The Token Expiration Redirect Refreshes:

You are designing a portal where session tokens expire after 30 minutes of inactivity. When a token expires, the application should automatically redirect the user to the login page, displaying a session expired message. Explain how you would implement this using React context, routing, and timers.

17. Quick Quiz

Q1: Which attribute is added to <Navigate> to replace the current entry in the browser's history stack?

A) clear

B) reset

C) replace

Answer: C — The replace attribute tells React Router to replace the active history entry rather than pushing a new one.

18. Summary & Key Takeaways

  • Protected Routes restrict access to authenticated users.
  • Use custom wrapper components to check user authorization before rendering route content.
  • Use the Navigate component with the `replace` attribute to trigger redirects safely.
  • Save target paths in location state to redirect users back to their original target after login.

19. Cheat Sheet

Router API Guard Element Purpose
<Navigate to="/path" replace /> Triggers a declarative redirect, replacing the active history entry.
const location = useLocation() Gets the current location object (used to save redirect paths).
location.state?.from?.pathname Reads the saved redirect target path after successful login.
---