All posts

Authenticated Protected Role-based Routing using Next.js and HOC

Implementing Authenticated Protected Role-based Routing using Next.js and HOC

8 Dec 20223 min read
Implementing Authenticated Protected Role-based Routing using Next.js and HOC

Hellllooooooo!

Hope you're doing great! This is SMY! ๐Ÿ‘‹

In this article, we are going to learn about Implementing Authenticated Protected Role-based Routing using Next.js and HOC.

Part 2: https://smy.hashnode.dev/validate-user-path-access-on-edge-with-nextauth-nextjs-middleware

Contents:

  • โšก My Story and Explanation

  • โšก Implementation of Role-based Routing using HOC

**Let's start **๐Ÿš€

Routing is one of the most used parts of Web Development today. Routing allows us to effectively switch between different pages.

In my experience, routing through the React Router Dom library in a React application is way more powerful than in Next.js since developers have the upper hand in implementing Routing in their own, and custom way. Next.js on one hand gives developers the feasibility of not having to configure routing is great for a simple application but becomes difficult once you have multiple roles and conditions.

I've found 3 ways of implementing Role-based protected Routing using Next.js, and the first one is using HOC.

Implementation of Routing using HOC:

Constant Roles

roles.ts

const Roles = {
  customer: 'customer',
  admin: 'admin'
};

export default Roles;

Created a constant Roles file to stay consistent

Constant RouteNames

RouteNames.ts

export const RouteNames = {
  login: '/auth/login',
  signup: '/auth/signup',
  dashboard: '/dashboard',
  admin: '/admin',
};

export default RouteNames;

Created a constant RouteNames file to stay consistent

RouteConfig

RouteConfig.ts

import Roles from '../utility/roles';
import { RouteNames } from './RouteNames';

const routeConfig: { [key: string]: { [key: string]: string } } = {
  auth: {
    default: RouteNames.login,
    [RouteNames.signup]: RouteNames.signup,
    [RouteNames.login]: RouteNames.login,
  },
  [Roles.customer]: {
    default: RouteNames.dashboard,
    [RouteNames.dashboard]: RouteNames.dashboard,
  },
  [Roles.admin]: {
    default: RouteNames.admin,
    [RouteNames.admin]: RouteNames.admin,
  },

};

export default routeConfig;

Created a constant Route Configs which contains configuration as to which role has access to which page, and its default page.

withAuth HOC

withAuth.ts

import { useRouter } from 'next/router';
import React, { useEffect, useState } from 'react';
import { getAuthState } from '../store/slices/authSlice';
import { useSelector } from '../store/store';
import routeConfig from './RouteConfig';

const withAuth =
  (Component: React.FC) =>
  (allowedRole: string) =>
  (props: any) => {
    // getting the auth state from redux store
    const { isLoggedIn, role } = useSelector(getAuthState);
    const router = useRouter();

    // using a state to keep track if user is in correct state or path
    const [isValidRoute, setIsValidRoute] = useState(false);

    useEffect(() => {
      // first condition is to check if logged in and if on wrong path
      // then route to default route of the particular role user is of

      if (
        isLoggedIn &&
        (!(role === allowedRole) ||
        !routeConfig[role][router.pathname])
      ) {
        setIsValidRoute(false);
        router.push(routeConfig[role].default);
      }

      // second condition is to check if not logged in and if on wrong path
      // then route to default not authenticated path
      else if (!isLoggedIn && !routeConfig.auth[router.pathname]) {
        setIsValidRoute(false);
        router.push(routeConfig.auth.default);
      }

      // if upper two conditions are not met then the route user is in correct and return the component
      else setIsValidRoute(true);
    }, []);

    return isValidRoute ? <Component {...props} /> : null;
  };

export default withAuth;

using withAuth HOC on pages

dashboard.ts

import React from 'react';
import { NextPage } from 'next';
import withAuth from '../../routes/withAuth';
import Roles from '../../utility/roles';

const Dashboard: NextPage = () => {
  return <h1>Dashboard</h1>;
};

// See how we are passing the valid Role through the second currying
export default withAuth(Dashboard)(Roles.customer);

Wrapping Up:

That's the HOC way of implementing Authenticated Protected Role-based Routing using Next.js.

Stay tuned, where I will cover two more ways

That's it, folks! hope it was a good read for you. Thank you! โœจ

๐Ÿ‘‰ Follow me:

GitHub

LinkedIn