How to Secure BrowserRouter in React
Securing routes in a React application using
BrowserRouter involves restricting access to specific
components based on the user’s authentication status. Since React is a
client-side library, security cannot be enforced solely on the frontend;
instead, you must protect your client-side routes to provide a clean
user experience while relying on backend API authorization for actual
data security. This article explains how to implement a reusable
Protected Route component using React Router v6 to safeguard your
application’s pages.
Understanding Client-Side Security in React
When using BrowserRouter, all JavaScript code is
downloaded to the user’s browser. This means you cannot completely
“hide” code from a determined user. Frontend security is about
user experience (UX)—preventing unauthorized users from
navigating to pages they shouldn’t see. True security must always be
enforced on your backend server by validating access tokens (like JWTs)
before returning sensitive data.
Step 1: Create a Protected Route Wrapper
The standard way to secure routes in React Router v6 is by creating a wrapper component. This component checks if the user is authenticated. If they are, it renders the child components; if not, it redirects them to a login page.
Create a file named ProtectedRoute.jsx:
import React from 'react';
import { Navigate, Outlet } from 'react-router-dom';
const ProtectedRoute = ({ isAuthenticated, redirectPath = '/login' }) => {
if (!isAuthenticated) {
return <Navigate to={redirectPath} replace />;
}
return <Outlet />;
};
export default ProtectedRoute;In this component: * isAuthenticated: A
boolean prop indicating the user’s login status. *
Navigate: A React Router component that
redirects the user. The replace prop ensures the
unauthorized page is replaced in the browser history stack. *
Outlet: A React Router component that
renders the child routes of the parent route wrapper.
Step 2: Implement Protected Routes in App.jsx
Now, apply the ProtectedRoute wrapper inside your main
routing configuration. Group your private routes under this wrapper
component.
import React, { useState } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import ProtectedRoute from './ProtectedRoute';
// Mock components
const Home = () => <h2>Public Home Page</h2>;
const Login = () => <h2>Login Page</h2>;
const Dashboard = () => <h2>Secure Dashboard</h2>;
const Settings = () => <h2>Secure Settings</h2>;
function App() {
// Replace this state with your actual authentication hook or context provider
const [user, setUser] = useState(null);
const isAuthenticated = !!user;
return (
<BrowserRouter>
<Routes>
{/* Public Routes */}
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
{/* Secured Routes */}
<Route element={<ProtectedRoute isAuthenticated={isAuthenticated} />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Route>
{/* Fallback Route */}
<Route path="*" element={<h2>Page Not Found</h2>} />
</Routes>
</BrowserRouter>
);
}
export default App;Step 3: Handle Role-Based Access Control (Optional)
If your application requires different levels of authorization (e.g.,
Admin vs. User), you can extend the ProtectedRoute
component to check for user roles.
Modify ProtectedRoute.jsx to accept allowed roles:
import React from 'react';
import { Navigate, Outlet } from 'react-router-dom';
const ProtectedRoute = ({ isAuthenticated, userRole, allowedRoles, redirectPath = '/unauthorized' }) => {
if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}
if (allowedRoles && !allowedRoles.includes(userRole)) {
return <Navigate to={redirectPath} replace />;
}
return <Outlet />;
};
export default ProtectedRoute;You can then apply it to admin-only routes in your routing configuration:
<Route
element={
<ProtectedRoute
isAuthenticated={isAuthenticated}
userRole={user.role}
allowedRoles={['admin']}
/>
}
>
<Route path="/admin" element={<AdminPanel />} />
</Route>By nesting your secure paths inside a central
ProtectedRoute component, you ensure a consistent and
reliable user experience, keeping unauthorized eyes away from restricted
user interfaces while your API secures the data.