Routing is one of the central elements of a modern React application. With React Router 7, we have a powerful tool to build dynamic applications in which different pages and content are displayed depending on the user and context. But while the routing itself is relatively simple, it only gets exciting when you want to secure certain pages. In this article, you will learn how to create protected routes, regulate user access and make your application secure.
If you want to learn more about protecting your ReactJS application, check out our blog article.

Why do routes need to be protected?
Not every page of an app should be accessible to everyone. Imagine you have an app with an admin area, user profiles or paid premium content. Without a protection device, anyone who knows the URL could access these pages – and that’s a huge security risk!
There are several scenarios where protected routes are essential:
- Authenticated areas: Only logged-in users are allowed to access certain pages.
- Role-based access control: Only admins are allowed to see the backend.
- Payment models: Only paying customers can see premium content.
- Data protection: Confidential information should only be accessible to authorized users.
In this article, I will explain step by step how to implement protected routes in React Router 7 to make your application secure and professional.

What's new in React Router 7?
Before we look at the protected routes, let’s take a quick look at what has changed in React Router 7. The most important improvement is the optimization of performance and API designs:
- Better TypeScript support: fewer errors and more type safety.
- New data management: Load data more efficiently and structure your API calls
- Improved <route> handling: Dynamic routing has been optimized.
- Better synchronization with React 19: More future-proof for modern apps.
These improvements make it easier to define secure and flexible routes for your application.

Installation and basic configuration
If you do not yet have a React Router in your project, install it with :
npm install react-router-dom
Then you can define the basic structure with the new router:
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './Home';
import Dashboard from './Dashboard';
import Login from './Login';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/login" element={<Login />} />
</Routes>
</BrowserRouter>
);
}
export default App;
Nothing new so far – but now we come to protecting the routes!

Protect React Router 7 routes: The basics
1. Authentication vs. Authorization
There are two concepts you should understand before working with protected routes:
- Authentication: Who are you? A user logs in and receives an identity.
- Authorization: What are you allowed to do? A user receives certain rights based on their role.
In most applications, a user will receive a token after logging in that allows them access to certain routes. This token can then be checked before a route is loaded.
2. The easiest way: Redirect in case of missing login
A basic protection mechanism is a ProtectedRoute component that checks whether the user is logged in. If not, they are automatically redirected to the login page.
Here is an example implementation for a protected route:
import { Navigate } from "react-router-dom";
const ProtectedRoute = ({ children }) => {
const isAuthenticated = !!localStorage.getItem("token");
return isAuthenticated ? children : <Navigate to="/login" replace />;
};
And this is how you use this component:
<Route path="/dashboard" element={<ProtectedRoute><Dashboard /></ProtectedRoute>} />
As soon as a non-authenticated user attempts to visit the /dashboard page, they are automatically redirected to the login.

Advanced route security
3. Role-based access control
Not every user is the same! Imagine an app in which there are normal users, moderators and admins. While normal users only have access to their profile, moderators should be able to manage content and admins should be able to see the entire backend.
Here is an example of role-based access control:
const RoleBasedRoute = ({ children, allowedRoles }) => {
const user = JSON.parse(localStorage.getItem("user"));
return user && allowedRoles.includes(user.role) ? children : <Navigate to="/unauthorized" replace />;
};
Use of this component:
<Route path="/admin" element={<RoleBasedRoute allowedRoles={["admin"]}><AdminPanel /></RoleBasedRoute>} />
4. Validate access with tokens
In many modern apps, JSON Web Tokens (JWT) are used to authenticate users. These tokens can be stored in the LocalStorage, in an internal state (recommended) or in cookies. When a route is loaded, the token is checked and the user is only allowed to see the page if it is valid.
5. Protection of API routes
Not only UI routes need to be protected – API endpoints should also only be available to authorized users. In combination with protected routes in React, you should also secure your backend.
fetch("/api/data", {
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`
}
});
This means that only an authenticated user has access to the data.
6. Authentication with Context API
A global Auth-Context can help to manage the authentication status centrally:
import { createContext, useContext, useState } from 'react';
const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const login = () => setIsAuthenticated(true);
const logout = () => setIsAuthenticated(false);
return (
<AuthContext.Provider value={{ isAuthenticated, login, logout }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => useContext(AuthContext);
Then we adapt our ProtectedRoute component:
import { useAuth } from './AuthContext';
const ProtectedRoute = ({ children }) => {
const { isAuthenticated } = useAuth();
return isAuthenticated ? children : <Navigate to="/login" />;
};
Now we can use the Auth-Provider in our app:
<AuthProvider>
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/dashboard" element={
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
} />
</Routes>
</BrowserRouter>
</AuthProvider>
7. Login- und Logout-Handling
Here is a simple login component that uses the Auth-Context:
import { useAuth } from './AuthContext';
import { useNavigate } from 'react-router-dom';
const Login = () => {
const { login } = useAuth();
const navigate = useNavigate();
const handleLogin = () => {
login();
navigate('/dashboard');
};
return (
<div>
<h2>Login</h2>
<button onClick={handleLogin}>Einloggen</button>
</div>
);
};
export default Login;
A logout button can look like this:
import { useAuth } from './AuthContext';
const LogoutButton = () => {
const { logout } = useAuth();
return <button onClick={logout}>Logout</button>;
};
export default LogoutButton;
Conclusion: Secure React routes made easy!
With React Router 7, protecting routes is easier than ever. Through a combination of protected routes, role-based routing and token validation, you can ensure that only authorized users see the right content.
The most important takeaways:
✅ Use ProtectedRoute component to redirect non-logged-in users.
✅ Introduce role-based authentication to manage different user groups.
Store tokens securely and optimize API calls.
✅ Do not issue sensitive error messages to avoid giving attackers any clues.
✅ Implement fallback mechanisms to avoid endless loops.
✅ Keep your code clear and maintainable with a central auth context
With these techniques, you are well equipped to build a secure and robust React application with protected routes. Good luck with the implementation! 🚀
If you would like to have your ReactJS application examined for vulnerabilities by an ethical hacker, you can find suitable ones on our cyber security marketplace.