DEV Community

Cover image for Route Guards in React: Securing Your Application
Vishal Yadav
Vishal Yadav

Posted on

Route Guards in React: Securing Your Application

Why Do We Need Route Guards?

Route guards are crucial for maintaining the security and integrity of your application. Here’s why you should use them:

  1. Protect Sensitive Information: Route guards prevent unauthorized users from accessing restricted areas containing sensitive data.
  2. Prevent Confusion: They help redirect unauthenticated users to appropriate pages, like the login page.
  3. Role-Based Access Control: You can implement role-based access with route guards, allowing different users (e.g., admins, regular users) to access different parts of the application.

Steps to Implement Route Guards

Let’s walk through the steps to add route guards in React using React Router v6, which is the recommended version for implementing route guards effectively.


Step 1: Public & Private Components

Create components for public and protected routes:

// PublicPage.jsx
const PublicPage = () => {
  return <p>This is a public route.</p>;
};
export default PublicPage;
Enter fullscreen mode Exit fullscreen mode
// PrivatePage.jsx
const PrivatePage = () => {
  return <div>This is a protected route.</div>;
};
export default PrivatePage;
Enter fullscreen mode Exit fullscreen mode

Step 2: Create Auth Context Provider

Set up a global context to manage authentication:

// AuthenticationProvider.jsx
import { createContext, useState } from "react";

export const AuthenticationContext = createContext({});

export function AuthenticationProvider({ children }) {
  const [userAuth, setUserAuth] = useState(null); // Initialize to null for unauthenticated state

  return (
    <AuthenticationContext.Provider value={{ userAuth, setUserAuth }}>
      {children}
    </AuthenticationContext.Provider>
  );
}
export default AuthenticationProvider;
Enter fullscreen mode Exit fullscreen mode

The AuthenticationProvider component wraps the app and provides authentication data to any component that needs it.


Step 3: Custom Hook for Authentication

Create a custom hook to retrieve and update the authentication state:

// useAuthentication.jsx
import { useContext } from "react";
import { AuthenticationContext } from "./AuthenticationProvider";

const useAuthentication = () => {
  return useContext(AuthenticationContext);
};

export default useAuthentication;
Enter fullscreen mode Exit fullscreen mode

This hook allows us to easily access the authentication context from any part of the app.


Step 4: Guard Component

This component protects routes and redirects users if they are not authenticated:

// ProtectRoute.jsx
import { Navigate, Outlet } from "react-router-dom";
import useAuthentication from "./useAuthentication";

const ProtectRoute = () => {
  const { userAuth } = useAuthentication();
  return userAuth ? <Outlet /> : <Navigate to="/" />;
};

export default ProtectRoute;
Enter fullscreen mode Exit fullscreen mode

If the user is authenticated, the component renders its children (<Outlet />), otherwise, it navigates to the home page.


Step 5: Implementing Routes

Finally, set up public and private routes using React Router:

// AppContainer.jsx
import { BrowserRouter, Route, Routes } from "react-router-dom";
import AuthenticationProvider from "./AuthenticationProvider";
import PublicPage from "./PublicPage";
import PrivatePage from "./PrivatePage";
import ProtectRoute from "./ProtectRoute";

const AppContainer = () => {
  return (
    <div className="App">
      <BrowserRouter>
        <AuthenticationProvider>
          <Routes>
            <Route path="/" element={<PublicPage />} />
            <Route element={<ProtectRoute />}>
              <Route path="/dashboard" element={<PrivatePage />} />
            </Route>
          </Routes>
        </AuthenticationProvider>
      </BrowserRouter>
    </div>
  );
};

export default AppContainer;
Enter fullscreen mode Exit fullscreen mode

In this example, /dashboard is a protected route and can only be accessed by authenticated users.


Final Thoughts

Using route guards in React ensures that only authorized users can access certain parts of your application. By combining React Router with context and custom hooks, we can easily secure routes and manage user access.

Additional Considerations

  • Persisting Authentication State: To maintain the authentication state across page refreshes, consider using localStorage or cookies to store the user's authentication token. This way, you can check the token on app load to determine the user's authentication status.

  • Server-Side Validation: Remember that client-side checks alone are not sufficient for security. Always validate user permissions on the server side to ensure that users cannot access restricted resources.

If you found this blog helpful and want to support, feel free to buy me a coffee!


References

  1. Upstatement. (2024). React Router Guards.
  2. Amrita Padhy. (2024). All about router guards in React JS.
  3. Netcetera. (2024). How to create guarded routes for your React-App.
  4. UI.dev. (2024). Protected Routes and Authentication with React Router.
  5. Technostacks. (2024). 33 React Best Practices For 2024.

This updated blog post incorporates the latest practices for implementing route guards in React, ensuring that it is relevant for developers in 2024.

Citations:
[1] https://github.com/Upstatement/react-router-guards
[2] https://dev.to/amritapadhy/all-about-router-guards-in-react-js-50b6
[3] https://blog.netcetera.com/how-to-create-guarded-routes-for-your-react-app-d2fe7c7b6122?gi=36bc81efa897
[4] https://www.angularminds.com/blog/protected-routes-in-react-router-authentication-and-authorization
[5] https://www.reddit.com/r/reactjs/comments/1cck2zd/need_help_to_implement_routeguardauthguard_on_my/
[6] https://ui.dev/react-router-protected-routes-authentication
[7] https://stackoverflow.com/questions/31084779/how-to-restrict-access-to-routes-in-react-router
[8] https://technostacks.com/blog/react-best-practices/

Top comments (0)