Role-Based Access Control (RBAC): Permissions vs. Roles

Once we’ve determined that a user is who they say they are (authentication), we next need to determine whether they can access the page or resource they’re trying to access (authorization). Role-Based Access Control (RBAC) is one of the most common ways enterprise software accomplishes this. It is highly flexible and allows for any number of configurations.

We’ll talk high level here about what roles and permissions are, how they work together and how we can use them to check for access.

Roles often align with job functions, but it’s definitely possible that they don’t, depending on our context.

For example, if we’re building an e-commerce site, we might have a full admin who can do things like create new products, change inventory, view orders, fulfill orders, add users, etc.

We might have someone who works in fulfillment who can view and fulfill orders, and perhaps someone else in accounting who should only be able to view orders, but not change anything.

Roles in these examples might be things like admin, fulfillment manager, accounting admin, etc.

A user may also have multiple roles, or, to simplify that process, roles can be hierarchical (one role encapsulates multiple other roles, and thereby contains all the permissions within). This is where that flexibility comes in!

Permissions are specific and resource-based - they define whether or not a person has access to a specific resource. This may be based on either the type of resource, or a specific resource - for example, a user might be able to edit all products, or they may be able to edit only products D and Y.

Using our example from above, examples of permissions might be view product, edit products, view orders, fulfill orders, or add users.

These can be as granular or as broad as necessary, but the more granular they are, the more control we have over who can do what - which after all, is the whole point! And since roles can be assigned multiple permissions, there’s no compelling reason to not err on the side of making them more granular.

Roles have a specific set of permissions assigned to them. They are effectively named groups of permissions.

For example, someone with the fulfillment manger role might have permission to view orders, fulfill orders, and refund orders. They are also not mutually exclusive. The accounting manager may also be able to view orders, but they won’t be able to fulfill or refund them, while they can view aggregate analytics, which the fulfillment manager cannot.

This means that when we’re going through the application logic that requires checking whether the current user is authorized to access or change a given resource, we should always check whether they have the appropriate permission, not whether they have the correct role.

Doing access checks according to permissions not roles means that:

  • We only have to check one thing. Instead of checking if someone is either an accounting manager OR a fulfillment manager before allowing them to view the orders list, we can just check that they have the view order permission
  • We can add or remove permissions from roles without changing our application logic. If we remove the refund order permission from the fulfillment manager role, instead of removing that role from the check before we allow a user to do this, we can just remove that permission from the role, and then when we check whether a user has that specific permission, we will be told that they do not. This works for adding permissions to roles, or even adding new permissions altogether.
  • We can add or remove roles without having to change our application code. If we need a new role that encapsulates a different set of permissions than is currently configurable, we can create that and assign it to users, and the application code can continue checking only whether the user has a given permission.