Bossadi Zenith

Apr 14, 2025 • 4 min read

Role base access control

Access control simplified

Role base access control

if you're a developer/engineer building softwares, there're two questions you need to answer while buiilding an application

  1. Who are you?

  2. What are you allowed to do?

These are two common questions that goes into what is called Access Control

The first question talks more about Authentication where the user is identified by their credentials (username, password, email, etc)

The second question talks more about Authorization where the user is identified and their access is granted based on their role in the application.

In this article, we'll focus on the second question because that's the most difficult one to answer.

In authorization, we have 2 different types of roles:

  1. RBAC (Role-Based Access Control)

  2. ABAC (Attribute-Based Access Control)

RBAC is the most common one and it's what we'll focus on in this article.

Imagine this scenario without roles with this diagram below:

From the diagram, we can see that there're just 4 capabilities to be done by the users with just 5 users. Now if we expand this out to more users and more capabilities, this becomes a mess in our codebase if our users scale to 1000s, 10000s, 100000s, etc.

To solve this, we can use roles to group the users into different roles and then we can use the roles to authorize the users.

From the diagram, we see that we have something more simpler, nicer and scalable. And image that in the future, we get something(a feature) that we want only the Nurses and Doctors to do, we can just add them to the Nurse and Doctor roles and all the nurses and doctors will have access to it without having to change the code. Or a new users somes into place and is of type Lab Technician, we can just add them to the Lab Technician role and they will have access to the Lab Technician capabilities.

Now, let's dive into the code and see how we can implement this in our codebase.

Implementing RBAC in our codebase


type Permission = "write:orders" | "read:orders" | "read:lab" | "write:lab";

// now you might be asking, what's the use of the "":""?
// well, the first part is the action and the second part is the resource
// for example, "write:orders" means that the user has the ability to write to the orders resource
// and "read:orders" means that the user has the ability to read the orders resource
// so we can group them together in a single permission

type Role = "Doctor" | "Nurse" | "LabTechnician";

const rolePermissions: Record<Role, Permission[]> = {
  Doctor: ["write:orders", "read:orders"],
  Nurse: ["read:orders", "read:lab"],
  LabTechnician: ["read:lab", "write:lab"],
};

interface User {
  id: string;
  name: string;
  role: Role;
}

const users: User[] = [
  { id: "u1", name: "Dr. John", role: "Doctor" },
  { id: "u2", name: "Nurse Alice", role: "Nurse" },
  { id: "u3", name: "Nurse Bob", role: "Nurse" },
  { id: "u4", name: "Nurse Clara", role: "Nurse" },
  { id: "u5", name: "Nurse Dave", role: "Nurse" },
  { id: "u6", name: "Tech Emma", role: "LabTechnician" },
  { id: "u7", name: "Tech Frank", role: "LabTechnician" },
];

// Helper to get permissions for a user
function getUserPermissions(user: User): Permission[] {
  return rolePermissions[user.role];
}

// Lets check if the users have the permissions to do the actions

export function checkPermission(user: User, permission: Permission): boolean {
  const userPermissions = getUserPermissions(user);

  if (!userPermissions) return false;

  return userPermissions.includes(permission);
}
console.log(checkPermission(users[0], "write:orders"));

This will return true because the doctor has the permission to write to the orders.

console.log(checkPermission(users[1], "write:orders"));

This will return false because the nurse does not have the permission to write to the orders.

And so on and so forth.

Now, let's say we want to add a new role called Admin that has all the permissions.

const rolePermissions: Record<Role, Permission[]> = {
  ...rolePermissions,
  Admin: ["write:orders", "read:orders", "read:lab", "write:lab"],
};

Now, we can use the checkPermission function to check if the user has the permission to do the action.

console.log(checkPermission(users[0], "write:orders"));

This will return true because the admin has the permission to write to the orders.

Now that we've seen how to implement RBAC, I guess you know see that authentication is usually the easier part. While the authorization, is where there's more of the fun, because you have to to check the exact level of access for each user. and that's where RBAC comes in.

Conclusion

RBAC is a simple and effective way to manage access control in your application. It's a great way to start with access control and it's a great way to scale your application.

I hope you enjoyed this article. If you have any questions, please feel free to reach out to me on .

Thank you for reading.

References

Join Bossadi on Peerlist!

Join amazing folks like Bossadi and thousands of other people in tech.

Create Profile

Join with Bossadi’s personal invite link.

0

2

0