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

Amit Kumar RoutAmit Kumar Rout
3 min read

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!

0
Subscribe to my newsletter

Read articles from Amit Kumar Rout directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Amit Kumar Rout
Amit Kumar Rout

I am a passionate and skilled developer with over a year of experience in building and deploying web applications. My expertise lies in frontend technologies, and I have a strong understanding of how to create user-friendly and visually appealing interfaces. I am also proficient in deploying applications using Nginx, ensuring optimal performance and reliability. Currently, I am expanding my knowledge by exploring the Rust programming language, eager to apply its unique features to my development projects.