Role-based access control starts tidy. A year later there are forty roles, three of them called some variant of "admin", several that nobody holds and one that was copied from another and never edited. Nobody can say with confidence what a given person is able to do. The model is not at fault. RBAC needs a small amount of regular maintenance, and that maintenance needs the right view of the data.

The four parts of RBAC

RBAC has four moving parts. Keeping them separate in your head, and in your schema, prevents most of the mess.

Permissions

A permission is the smallest unit: one action on one kind of resource. A consistent key format helps, for example action:resource.

read:users
manage:users
read:audit
manage:roles
approve:response

Permissions should be defined by the system that enforces them. A permission that no code checks is a label, not a control.

Roles

A role is a named set of permissions. It describes a job to be done: "user administrator", "auditor", "billing manager". A role does not name any person.

Subjects

A subject is anything that can hold a role: a person, a group, an application, a service account, an AI agent.

Bindings

A binding connects a subject to a role, sometimes within a scope such as one project or one customer organisation. Bindings are where access is actually granted.

The separation matters because the three questions people ask map to different parts. "What can this role do" is answered by the role's permissions. "Who holds this role" is answered by bindings. "What can this person do" is the union of the permissions of every role bound to them, directly or through a group.

Bind groups, not people

Binding roles directly to individuals works until the second person joins the team. After that, every joiner needs the same four bindings their colleagues have, and every leaver needs them removed.

The better pattern is one more level of indirection:

  1. People belong to groups. Membership comes from your directory or from HR data, ideally provisioned automatically.
  2. Groups are bound to roles.
  3. A person's access changes when their group membership changes, and for no other reason.

Direct bindings to a person should be the exception, visible as an exception, and preferably carry an end date. A temporary grant that lapses on its own is safer than one that relies on somebody remembering to remove it.

System roles and your own

Most platforms ship with a set of built-in roles: owner, administrator, read-only and a handful of others. These are system roles. Roles you define yourself are custom roles. They should be treated differently.

A system role is part of the product. Its meaning should be the same in every tenant, and the vendor should be able to add a permission to it when a new feature ships. That argues for three properties:

  • System roles are read-only to tenants. If each tenant can edit its copy of "Administrator", the name stops meaning anything, and the next product update either overwrites the edit or silently skips that tenant.
  • System roles cannot be deleted. Something must always be able to administer the tenant.
  • Customisation happens by copying. Duplicate the system role as a custom role and edit the copy. The copy is yours and will not change underneath you.

Custom roles are where least privilege is won or lost. A good custom role is narrow, named after a task and built by adding permissions to an empty set, not by removing them from a copy of administrator.

Finding the roles that should not exist

RBAC decays in a few recognisable ways. Each can be found with a simple query, provided the data is in one place.

  • Roles held by nobody. A role with no bindings grants nothing today. It is a risk tomorrow, when someone binds it without checking what it contains. Delete it, or record why it is kept.
  • Roles that grant nothing. A role with no permissions looks like access and is not. People holding it believe they have been given something. It is usually a half-finished setup.
  • Permissions carried by no role. Either the feature behind the permission is unused, or people are reaching it through a broader role than they need.
  • The broadest roles. Sort roles by the number of permissions they carry and by the number of holders. A role that is both broad and widely held is your real attack surface, whatever it is called.
  • Direct bindings. People who hold a role individually when their team's group already has it, or has a narrower one.

Running a least privilege review

A review that tries to examine every permission of every person does not finish. A review that follows a fixed order, starting with what is cheapest to fix, does.

  1. Remove the dead weight. Delete roles held by nobody and fix or delete roles that grant nothing. This shrinks the problem before any hard decisions.
  2. Review the broadest roles first. For the few roles with the most permissions, list the holders and ask whether each one still needs it. Aim to move people to a narrower role, not only to remove them.
  3. Check non-human holders. Applications, service accounts and agents collect roles and never ask for them to be taken away. Each should have a named owner who can justify the binding.
  4. Convert direct bindings to groups, or put an end date on them.
  5. Compare granted with used. If your audit record shows that a permission has never been exercised by a holder, that is evidence for removing it. See an audit record you can query.
  6. Preview before you save. Before changing a role's permissions, list who holds it. Editing a role changes access for every holder at once, and the change should say so.

Do this on a schedule, and keep the output: what was reviewed, what was removed and who decided. For the most sensitive permissions, pair the role with a step-up check.

How AuthFI does it

The AuthFI console has a Roles and permissions area built around these questions. Its overview shows six figures: roles, roles held by nobody, roles that grant nothing, role holders, permissions, and permissions carried by no role. Each figure opens its list already filtered, next to a "Needs a look" list and the broadest roles.

A role's page has three sections: what it grants, grouped by resource, its permissions, and who holds it. Holders can be people, groups, agents or applications, and a binding can be taken away in place. Permission edits are staged, and the confirmation says who the change reaches.

System roles are read-only in the console. To get a different set of permissions you duplicate one as a custom role, which you can then rename, edit or delete. The permission catalogue shows which roles carry each permission, and both lists can be downloaded as CSV for a review.

Access to applications, cloud roles and servers follows the same groups, so adding someone to a group changes their access everywhere, and a grant can carry an end date and lapse on its own.

Key takeaways

  • Keep permissions, roles, subjects and bindings separate. Each answers a different question.
  • Bind roles to groups, and make direct bindings to people rare, visible and time-limited.
  • Leave system roles alone and customise by copying.
  • Look for roles nobody holds, roles that grant nothing and the roles that are both broad and widely held.
  • Review in a fixed order, preview who a change reaches and keep a record of what was decided.