Authorization Guards with React Router

Authorization guards prevent unauthorized users from accessing the web page when they are not supposed to see it and redirect them to unauthorized page.

Image by knerri61 on Pixabay

First, define Routes as follows with React Router. It has 4 types of routes

  1. Public routes
  2. Read-Only user routes
  3. Reports routes
  4. Sys Admin routes
import {Route, Switch} from "react-router-dom";
import Home from "../components/home/Home";
import NotFound from "../components/core/404/NotFound";
import React from "react";
import Login from "../components/core/login/Login";
import Logout from "../components/core/logout/Logout";
import UnAuthorized from "../components/core/unauthorized/UnAuthorized";
import {AdminGuardedRoute} from "./AdminGuardedRoute";
import ManageAdGroup from "../components/admin/groups/ManageAdGroup";
import {ReadOnlyAccessGuardedRoute} from "./ReadOnlyAccessGuardedRoute";
import {DataUserGuardedRoute} from "./DataUserGuardedRoute";
import ReportsSearch from "../components/reports/ReportsSearch";
import useAuthService from "../hooks/useAuthService";


/**
 * Define all Routes and Sub-Routes
 *
 * @author Pavan Kumar Jadda
 * @since 1.0.0
 */
export default function Routes(): JSX.Element {
    const {isReadOnlyUser, isDataUser, isPsoManager, isSysAdmin} = useAuthService();
    return <div>
        <Switch>

            {/* Read Only User Routes */}
            <ReadOnlyAccessGuardedRoute component={Home} path={"/"} isAuthorized={isReadOnlyUser()}
                                        exact={true}/>
            <ReadOnlyAccessGuardedRoute component={Home} path={"/home"} isAuthorized={isReadOnlyUser()}
                                        exact={true}/>

                                        
            {/* Reports Routes */}
            <DataUserGuardedRoute component={ReportsSearch} path={"/report"} isAuthorized={isDataUser()}
                                  exact={true}/>

            {/* Admin Routes */}
            <AdminGuardedRoute component={ManageAdGroup} path={"/admin/group/manage"}
                               isAuthorized={isSysAdmin()} exact={true}/>

            {/* Core Routes */}
            <Route component={Login} path={"/login"} exact={true}/>
            <Route component={Logout} path={"/logout"} exact={true}/>
            <Route component={UnAuthorized} path={"/unauthorized"} exact={true}/>
            <Route component={NotFound} path={"*"}/>

        </Switch>
    </div>;
}

The system supports 3 types of users

  1. Read Only User (ReadOnlyAccessGuardedRoute)
  2. Reports User (DataUserGuardedRoute)
  3. Sys Admin (AdminGuardedRoute)

Each type of user routes are protected by different route guards. For example Read-Only Access Guarded route prevents users from accessing web pages without READ_ONLY_USER role, Reports routes need DATA_USER role and Sys admin routes need SYS_ADMIN role.

Each Guarded Route receives an attribute called isAuthorized, which tells if the user authorized to access the route or not. This information should be defined in Routes and passed to each Guarded Route.

All of these guards follow one simple structure. If the user is not logged in redirect user to Login page, if unauthorized and does not have access/roles to access it, redirect to /unauthorized page otherwise proceed to the original request

Take a look at Read-Only Access Guarded Route below

import * as React from 'react';
import {Redirect, Route,} from 'react-router-dom';
import ReactIf from "../components/shared/ReactIf";
import useAuthService from "../hooks/useAuthService";

export function ReadOnlyAccessGuardedRoute(props: { component: any; path: string; isAuthorized: boolean, exact: boolean }): JSX.Element {
    const {component: Component, isAuthorized, ...rest} = props;
    const {isUserLoggedIn} = useAuthService();
    return (
        <Route
            {...rest}
            render={(routeProps) =>
                <div>
                    {/* If not logged in, redirect to Login page */}
                    <ReactIf condition={!isUserLoggedIn()}>
                        <Redirect
                            to={{
                                pathname: '/login',
                                state: {from: routeProps?.location}
                            }}
                        />
                    </ReactIf>

                    {/* If logged in and has Read Only User role, navigate to component */}
                    <ReactIf condition={isUserLoggedIn() && isAuthorized}>
                        <Component {...routeProps} />
                    </ReactIf>

                    {/* If logged in but does not Read Only User role, navigate to Unauthorized page */}
                    <ReactIf condition={isUserLoggedIn() && !isAuthorized}>
                        <Redirect
                            to={{
                                pathname: '/unauthorized',
                                state: {from: routeProps?.location}
                            }}
                        />
                    </ReactIf>
                </div>
            }
        />
    );
}

and Sys Admin guarded route defined as follows

import * as React from 'react';
import {Redirect, Route,} from 'react-router-dom';
import ReactIf from "../components/shared/ReactIf";
import useAuthService from "../hooks/useAuthService";

export function AdminGuardedRoute(props: { component: any; path: string; isAuthorized: boolean, exact: boolean }): JSX.Element {
    const {component: Component, isAuthorized, ...rest} = props;
    const {isUserLoggedIn} = useAuthService();

    return (
        <Route
            {...rest}
            render={(routeProps) =>
                <div>
                    {/* If not logged in, redirect to Login page */}
                    <ReactIf condition={!isUserLoggedIn()}>
                        <Redirect
                            to={{
                                pathname: '/login',
                                state: {from: routeProps.location}
                            }}
                        />
                    </ReactIf>

                    {/* If logged in and has Sys Admin role, navigate to component */}
                    <ReactIf condition={isAuthorized}>
                        <Component {...routeProps} />
                    </ReactIf>

                    {/* If logged in but does not have Sys Admin role, navigate to Unauthorized page */}
                    <ReactIf condition={!isAuthorized}>
                        <Redirect
                            to={{
                                pathname: '/unauthorized',
                                state: {from: routeProps.location}
                            }}
                        />
                    </ReactIf>
                </div>
            }
        />
    );
}

Even though Read-Only Access Guarded Route and Sys Admin Access Guarded Route looks similar in reality we may have some additional conditions for each Guard.


Happy Coding 🙂

Pavan Kumar Jadda
Pavan Kumar Jadda
Articles: 36

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.