Intorduction
Managing user roles and permissions is a critical aspect of web application security and functionality. It ensures that users have appropriate access to different parts of the application based on their roles. In this article, I'll walk you through the implementation of a custom useRoleManagement hook in React, which decodes a JWT token to manage user permissions.
Setting Up
Before diving into the implementation, let's set up the necessary tools and libraries. You'll need:
- React
- jwt-decode for decoding JWT tokens
- react-router-dom for managing routing and extracting the current path
npm install react-router-dom jwt-decode
Implementation
Let's start by defining the interfaces for our permissions and JWT payload.
import { JwtPayload, jwtDecode } from 'jwt-decode';
import { useLocation } from 'react-router-dom';
// Realm is for authentication mechanism like Keycloak
interface Realm extends JwtPayload {
realm_access: {
roles: string[];
};
}
// Interface representing the user's permissions
interface Permissions {
add: boolean;
view: boolean;
edit: boolean;
confirm?: boolean;
include?: boolean;
deleteRow?: boolean;
}
// Interface representing the user's permissions for various pages
interface UserPermissions {
partners?: Permissions;
projects?: Permissions;
// More pages can be added here as needed
}
type PermissionKeys = keyof UserPermissions;
Next, we define the permissions for different roles:
const permissions = {
manager: {
partners: {
add: false,
view: false,
edit: false,
deleteRow: true,
},
projects: {
add: false,
view: false,
edit: false,
deleteRow: false,
},
// Define more pages
},
analyst: {
// Define permissions for analyst role
},
director: {
// Define permissions for director role
},
};
Check if Role Exists
We need a function to check if a role exists and return the associated permissions:
function ifRoleExists(roles: string[]) {
return roles
.map((role) => {
return permissions[role as keyof typeof permissions];
})
.filter(Boolean)[0];
}
Get Permissions for the Role
This function retrieves the permissions for a given role and path:
function getPermissions(roleExists: UserPermissions, pathName: string) {
const withoutSlash = pathName.replace('/', '') as PermissionKeys;
return roleExists?.[withoutSlash] ?? pathName;
}
useRoleManagement Hook
Finally, we implement the useRoleManagement hook:
export function useRoleManagement() {
const { pathname } = useLocation();
const token = localStorage.getItem('token');
let decodedToken: Realm | null = null;
try {
if (token) {
decodedToken = jwtDecode<Realm>(token);
}
} catch (error) {
console.error('Invalid token:', error);
}
const roles = decodedToken?.realm_access?.roles ?? [];
const roleExists = ifRoleExists(roles);
const rolePermissions = getPermissions(
roleExists,
pathname !== '/' ? pathname : '/partners',
);
if (!rolePermissions) {
return {};
}
const {
add,
view,
edit,
deleteRow,
confirm,
include,
} = rolePermissions as Permissions;
return {
add,
view,
edit,
deleteRow,
confirm,
include,
};
}
Usage Example
Here's how you can use the useRoleManagement hook in a React component:
import React from 'react';
import { useRoleManagement } from './useRoleManagement';
const Dashboard = () => {
const { add, view, edit, deleteRow } = useRoleManagement();
return (
<div>
{view && <p>You can view this content.</p>}
{add && <button>Add Item</button>}
{edit && <button>Edit Item</button>}
{deleteRow && <button>Delete Item</button>}
</div>
);
};
export default Dashboard;
Conclusion
In this article, we've implemented a custom useRoleManagement hook in React to manage user permissions based on their roles. This approach ensures that your application remains secure and that users have the appropriate access based on their roles. Feel free to customize the permissions and roles according to your application's requirements.
I hope you found this guide helpful. If you have any questions or suggestions, please leave a comment below!
Top comments (0)