Route Guard
Problem
Protected content briefly flashes on screen before auth checks redirect users, creating security concerns and poor user experience. Each route must manually check permissions, leading to scattered authentication logic and easy-to-miss security holes.
Solution
Check conditions before allowing navigation to protected routes, redirecting unauthorized users. This enforces authentication and authorization requirements at the routing level.
Example
This example shows a route guard that checks authentication before rendering protected content, redirecting unauthorized users to the login page.
function ProtectedRoute({ children }) {
// Check if user is authenticated
const { user } = useAuth();
// Redirect to login if not authenticated
if (!user) {
return <Navigate to="/login" />;
}
// Render protected content only if authenticated
return children;
}
// Wrap protected routes with the guard
<Route path="/dashboard" element={<ProtectedRoute><Dashboard /></ProtectedRoute>} />
Benefits
- Centralizes authentication logic instead of scattering it across components.
- Prevents protected content from briefly flashing before redirects.
- Makes security requirements explicit and easier to audit.
- Provides a declarative way to enforce access control.
Tradeoffs
- Can create poor UX if redirects aren’t handled smoothly.
- May need complex logic for role-based or conditional access.
- Requires careful handling of redirect destinations and return URLs.
- Can make testing harder if guards are tightly coupled to routing.