How to implement multi role based authorization in React

21,014

Solution 1

Please beware that this is not an optimal solution and only meant to give you some ideas.

Create a file RoleBasedRouting.jsx

function RoleBasedRouting({
  component: Component, roles, ...rest
}) {
  return (
    <>
      { grantPermission(roles) && (
      <Route
        {...rest}
        render={(props) => (
          <>
            <Component {...props} />
          </>
        )}
      />
      )}
      {
        !grantPermission(roles) && (
          <Route
            render={() => (
              <>
                <Unauthorized /> // Unauthorized Page View (skippable)
              </>
            )}
          />
        )
      }
    </>
  );
}

Use it in your Router like this -

<Switch>
     <RoleBasedRouting exact path="/admin" component={AdminPage} roles={['ROLE_ADMIN']} />
     <RoleBasedRouting exact path="/user" component={UserPage} roles={['ROLE_USER']} />
     <RoleBasedRouting exact path="/manager" component={ManagerPage} roles={['ROLE_Manager']} />
     ...............
</Switch>

In grantPermission function, check if the logged in user has the required roles. Sample -

export const grantPermission = (requestedRoles) => {
  const permittedRoles =  JSON.parse(localStorage.getItem('userRoles'));
 // in case of multiple roles, if one of the permittedRoles is present in requestedRoles, return true;
  return false;
};

To render UI conditionally, you can do basically the same thing. Write a component UnlockAccess -

const UnlockAccess = ({ children, request }) => {
  const permission = grantPermission(request); // request = ['ROLE_ADMIN'] / ['ROLE_USER'] / ['ROLE_MANAGER']
  return (
    <>
      {permission && children}
    </>
  );
};

Now, Use UnlockAccess component in the Dashboard page like this -

<Dashboard>
    <UnlockAccess request={['ROLE_ADMIN']}>
         <>
              {/*Write code/components for Admin Dashboard*/}
         </>                    
    </UnlockAccess>
    <UnlockAccess request={['ROLE_USER']}>
         <>
              {/*Write code/components for User Dashboard*/}
         </>                    
    </UnlockAccess>
    <UnlockAccess request={['ROLE_MANAGER']}>
         <>
              {/*Write code/components for Manager Dashboard*/}
         </>                    
    </UnlockAccess>
</Dashboard>

Solution 2

You should create different route components specifically for all roles, for example, AdminRoute, UserRoute, etc and in these components, you can check the weather login person is admin or a normal user.

or create a general route component and pass role and path there as props

Solution 3

You can use a HOC to check if the user accessing the route is allowed to access, i.e. if user is admin who is trying to access the admin dashboard is admin. If not then can redirect him to wherever you like.

export default function withAuth(WrappedComponent) {


const auth = (props) => {
    return (
        localStorage.getItem("userRole") === "admin" ?
        <WrappedComponent {...props} /> :
        <Redirect to = {{ 
            pathname: "/protected/login"
        }} />
    )
}

return auth;
}

Or you can maintain a features array in localStorage with features you wanna give access to your user.

Share:
21,014

Related videos on Youtube

Jonas
Author by

Jonas

Updated on March 09, 2020

Comments

  • Jonas
    Jonas about 4 years

    I am working on application where I have different multi role ( admin, user,manager ) I want to protect route of admin from manager and general user also render UI based on user role . I tried but I am failed could someone please help me how to achieve my goal . Example will be appreciated

    Thanks

    • Not A Bot
      Not A Bot about 4 years
      Can you post some of the code or approach you followed to achieve the task?
    • Jonas
      Jonas about 4 years
      @NotABot actually, I have different dashboard in my application , I want to show separate dashboard for different users like admin, manager etc
    • Not A Bot
      Not A Bot about 4 years
      What I am asking any logic you have applied for this?
    • Jonas
      Jonas about 4 years
      @NotABot no , currently I don't implement any logic . I am stuck , I wan to ask about logic
    • Not A Bot
      Not A Bot about 4 years
      See when you authenticate the user, then store the role of the user maybe in localStorage or any other storage which you are familiar with. Then before rendering the UI, just check what is the role of the user, and then render the UI.
  • Jonas
    Jonas about 4 years
    could you please write a simple example, it will help me to save a day
  • Jonas
    Jonas about 4 years
    thanks for your answer , could you please guide me what granPermission used for ?
  • Jonas
    Jonas about 4 years
    Great , How I can render UI conditionally . mean I want to render separate dashboard like admin,manager
  • Mark
    Mark about 4 years
    You can use different paths for each role or you can do the same thing for component rendering. I have updated the answer. Please check again.
  • Jonas
    Jonas about 4 years
    one more thing, when I try to console roles={['ROLE_ADMIN']} in rolebasedRouting.jsx I am getting all these three props. I want only requested route props (roles)
  • Mark
    Mark about 4 years
    can you share your code, your log and elaborate what are you trying to do
  • Jonas
    Jonas about 4 years