How to protect routes for different user roles with restricted access?

Introduction

Web applications often require different levels of access for various users. For instance, an administrator may need access to specific features that a regular user may not. One way to manage user access in your web application is by setting up protected routes.

In React, we use the 'react-router' package to set up public and protected routes. To install 'react-router' in a React application, you can use the following command: npm i react-router.

Prerequisites

  1. Knowledge on React,React-Router

  2. node > = 16.19.0

  3. react >= 18.2.0

  4. react-router-dom >= 6.9.0

Protected Route In most cases, for protected routes, users are logged out automatically if they are not authenticated. However, in a role-based application, if an authenticated user of a different role tries to access a route that is not permitted, the protection mechanism may be violated.

The goal is to redirect the user back to the previous URL if they try to access a route that is not permitted for their role. Firstly, the project file structure

Project Directory

In PageRouter.js

import {
    BrowserRouter as Router,
    Route,
    Routes,
} from "react-router-dom";

import LoginPage from "../pages/LoginPage";
import UserRegistration from "../pages/UserRegistration";
import AdminPage from "../pages/admin/AdminPage"
mport UserPage from "../pages/user/UserPage"

export const PageRouter = () => {

    return (
        <Router>
            <Routes>
                <Route exact path="/" element={<LoginPage />} />
                <Route exact path="/userReg" element={<UserRegistration />} />
                <Route exact path="/adminPage" element={<AdminPage />} />
                <Route exact path="/userPage" element={<UserPage />} />
            </Routes>
        </Router>
    )
}

Import PageRouter.js in app.js

Currently, there are two roles - "Admin" and "User" - for which we have created two files, ProtectedRouteAdmin.js and ProtectedRouteUser.js.

In ProtectedRouteAdmin.js

import {useEffect} from "react";
import { Route,Redirect, Navigate, Outlet, useNavigate, useLocation} from "react-router-dom";
import jwtDecode from "jwt-decode";
import axios from "axios";

const ProtectedRouteAdmin = (props) => {
  const token = localStorage.getItem("token");
  const navigate = useNavigate();
  function presentPage() {
    navigate(-1);
  }

  if (!token) return <Navigate to="/" />;

  useEffect(()=>{
    if(token && jwtDecode(token).role!== "admin"){ 
      presentPage()
      }
  },[token && jwtDecode(token).role!== "admin"])

  const decodedData = jwtDecode(token);


  if (decodedData.role === "admin") {
    return <Outlet {...props} />;
  }
 else if(decodedData.role!=="admin"){
   presentPage()
  }
};

export default ProtectedRouteAdmin;

And in ProtectedRouteUser.js

import {useEffect} from "react";
import { Route,Redirect, Navigate, Outlet, useNavigate, useLocation} from "react-router-dom";
import jwtDecode from "jwt-decode";
import axios from "axios";

const ProtectedRouteUser = (props) => {
  const token = localStorage.getItem("token");
  const navigate = useNavigate();
  function presentPage() {
    navigate(-1);
  }

  if (!token) return <Navigate to="/" />;

  useEffect(()=>{
    if(token && jwtDecode(token).role!== "user"){ 
      presentPage()
      }
  },[token && jwtDecode(token).role!== "user"])

  const decodedData = jwtDecode(token);


  if (decodedData.role === "user") {
    return <Outlet {...props} />;
  }
 else if(decodedData.role!=="admin"){
   presentPage()
  }
};

export default ProtectedRouteUser;

Updating code in PageRoute.js

//other imports
import ProtectedRouteAdmin from "./ProtectedRouteAdmin";
import ProtectedRouteUser from "./ProtectedRouteUser";

export const PageRouter = () => {
    return (
        <Router>
            <Routes>
                <Route exact path="/" element={<LoginPage />} />
                <Route exact path="/userReg" element={<UserRegistration />} />
               <Route element={<ProtectedRouteAdmin/>}>
                  <Route exact path="/adminPage" element={<AdminPage />} />
</Route>
               <Route element={<ProtectedRouteUser/>}>
                  <Route exact path="/usPage" element={<AdminPage />} />
</Route>
            </Routes>
        </Router>
    )
}

Conclusion The protected routes have been set up. Test them to ensure they are working correctly by logging in with different user roles and checking if they have access to the appropriate routes. If necessary, you can add Redux to check authorized routes. I hope this helps you to write Protected Routes in a better way! If you have any suggestions for improving the code, please leave them in the comments section. If you found this post helpful, please like and share it.

Happy Coding!