Data Analyse Breda

React JS: Create Protected Routes in React Router 6

In this blogpost we adress protected routes with React Router 6. Protected or Private routes make sure that users can access certain pages in your React application based on a set of rules.

Why are protected routes important?

You only want the users in your website to access the links that they are allowed to see. For example, I only want the users to be able to see a home page when they are logged in. If they are not logged in and they type in the link to the homepage (or click a link) I want them to be redirected to the login page.

A codesandbox example with the full code is included at the bottom of this article.

How do you do this?

To achieve this, we will follow these steps:

  • Create a file named protectedroutes.js which determines whether we can or cannot login.
  • Wrap our urls in the App.js file inside the protected routes element.

Create the protected routes file

We start with creating the file that will define the logic that is used to assess whether a user can have access to a certain page. Below a very basic example.

import { Navigate, Outlet } from "react-router-dom";

export default function ProtectedRoutes() {
  let auth = { token: true};
  return auth.token ? <Outlet /> : <Navigate to="/" />;
}
  • We start by importing Navigate and Outlet. Navigate enables us to redirect to other pages (this is the successor of Redirect) Outlet is used to serve as a parent for multiple child routes. This is convenient since we want to have several routes within our ProtectedRoutes element.
  • Next we create a function called ProtectedRoutes. In this function we first define a variable called auth. In this variable we store the information that defines whether the user is able to access the page.
  • In the ProtectedRoutes function we create an if statement. If the auth.token variable is true, we use the Outlet to wrap all of our children routes. If auth.token is false we redirect the user to the “/” page. In my case this is the login page.

Apply our logic to the frontend pages

We now want to apply this rule to some of our frontend urls. In order to achieve this we need to:

  • Import the ProtectedRoutes function into our App.js file.
  • Wrap the routes where we want to apply this logic in another Route component.
  • Add the ProtectedRoutes component as element of this Route component.
  • We do NOT wrap our Login route, since users can always access this page, regardless of their access rights.

Every time a user interacts with one of these pages the function is triggered, and the function will assess whether the user can access the page or needs to be redirected.

import { Route, Routes } from "react-router-dom";
import Home from "./components/home";
import About from "./components/about";
import Login from "./components/login";
import Navbar from "./components/navbar";
import ProtectedRoutes from "./protectedroutes";

export default function App() {
  return (
    <div className="App">
      <Navbar />
      <Routes>
        <Route element={<ProtectedRoutes />}>
          <Route path="/about" element={<About />} />
          <Route path="/home" element={<Home />} />
        </Route>

        <Route path="/" element={<Login />} />
      </Routes>
    </div>
  );
}

Output in CodeSandbox

Let’s see what our output looks like in a codesandbox environment. In this example I have set the auth.token variable at false. In the sandbox you will see that we will be redirected back to our login page when we try to click the Home or About items on the top.

import { Navigate, Outlet } from "react-router-dom";

export default function ProtectedRoutes() {
  let auth = { token: false};
  return auth.token ? <Outlet /> : <Navigate to="/" />;
}

If you go and change the variable to true, you will be able to go into the Home and About page. This is how the ProtectedRoutes function works.

Protected routes with Access & Refresh tokens

Right now we have hard coded the input of the auth token variable. But in your actual application, you will need to check your apps bespoke indicator for logging in.

perhaps your application uses Simple JWT to get access and refresh tokens from the backend when a users logs in. In that case, you need to check if an access or refresh token is present.

The example below specifies the code that checks whether a refresh token named refresh_token is present in the local storage. If it is, the user is logged in and can visit the page. If not, the user is redirected to the login page.

import { Navigate, Outlet } from "react-router-dom";

export default function ProtectedRoutes() {
  const refreshToken = localstorage.getItem('refresh_token')
  let auth = { token: refreshToken};
  return auth.token ? <Outlet /> : <Navigate to="/login" />;
}

Add more criteria to your protected routes

You can extend your protected routes with additional logic. For example, if you have different modules in your application, your can check whether the user should be able to access certain pages based on data in your application. You can also create different route criteria for certain routes. The options are endless!

Below an example that evaluates two criteria instead of 1. It evaluates whether both auth and isadmin are true. You can also change this to an OR statement by replacing && with ||.

import { Navigate, Outlet } from "react-router-dom";

export default function ProtectedRoutes() {
  let auth = { token: true };
  let isadmin = { hasadminrights: true };
  return auth.token && isadmin.hasadminrights ? (
    <Outlet />
  ) : (
    <Navigate to="/" />
  );
}

Leave a Reply