DEV Community

Amit Kumar Rout
Amit Kumar Rout

Posted on • Edited on

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>
    )
}


Enter fullscreen mode Exit fullscreen mode

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;


Enter fullscreen mode Exit fullscreen mode

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;


Enter fullscreen mode Exit fullscreen mode

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>
    )
}


Enter fullscreen mode Exit fullscreen mode

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!

Top comments (2)

Collapse
 
nickap profile image
nickap

interesting!
In Vue (using Vue Router) there are the "navigation-guards" someone can use to protect routes according to a user-role.
router.vuejs.org/guide/advanced/na...

Collapse
 
sandipskgit profile image
SandipShivaji

Insightful.Hope it works with SSO/Oauth also.is there any guide to integrate any authorization authentication?