Role-based Access Control
Method
Bundling permissions into roles like administrator and editor, then assigning people a role, rather than granting permissions person by person.
Why it exists
While permissions were granted person by person, the number of cells to manage grew by multiplication. Forty-five people and twenty kinds of permission means 900 cells to verify. Put it in a table and it doesn't fit on one screen, which means nobody reviews the whole thing and everybody reviews the row they came for.
So in practice it got handled by copying. Setting up a new hire meant duplicating a teammate's configuration. If that teammate carried one permission they didn't need, it came along. Six months later nobody remembers why it was there and nobody proposes removing it. This is how an audit turns up twelve accounts holding a delete permission none of them had reason to use. Each one traces back to a copy made in a hurry on somebody's first day.
Offboarding hit the same problem. Locking the account gets remembered; where that person's individually granted permissions lived isn't written down anywhere. Authentication, confirming who arrived, happens in one place at login, while authorization, judging whether that confirmed person may do what they just asked, was scattered across people.
How to run it
The work is detaching permissions from people and attaching them to roles, in five steps.
- Write the permissions as a list. Write them as actions, not screens. "Access the settings page" bundles six distinct actions into one cell, so split them: invite a member, view billing details, permanently delete a document. The split is what makes the next two steps possible at all, because a role can only be as precise as the list it draws from.
- Define the roles. Start from what people actually do rather than from the org chart. For a collaborative document product, owner, administrator, editor, commenter, and viewer is usually enough. Past about twenty roles you're back to granting permissions per person, with the added cost of a system that looks like it has structure.
- Attach permissions to roles. Build a table with roles as rows and permissions as columns, and mark the cells. The standard for filling it is least privilege, granting only what's needed. If an editor has no reason to see billing details, that cell stays empty.
- Attach roles to people. One role per person is the default. Allow roles to stack and permissions compute as a union, which produces a state where each role is safe and someone holding two of them can do something nobody intended. Auditing that state means checking combinations rather than roles, and the number of combinations is what you were trying to escape.
- Revisit on a cycle. Once a quarter, look at headcount per role and actual usage. Twenty people holding the administrator role usually means the role design is wrong, and a permission no role has exercised in six months is a candidate for removal.
Roles alone aren't enough, so scope comes with them. The same editor may be an editor of an entire workspace or of one document. In practice roles and scopes get paired, so one person is an administrator in workspace A and a viewer in workspace B. Without scope the only honest options are administrator everywhere or administrator nowhere, and teams pick the first one.
When it fits and when it doesn't
Three situations suit it: organizations grown past hand management, organizations where job functions divide cleanly, and cases where who-can-do-what has to be shown externally. The last one carries real weight. When a security review asks you to explain the permission model, one table of roles and permissions answers it, and the same table answers it again next year.
Where it doesn't fit is equally clear. Three cases.
- Conditions roles can't express — "only documents I created," "only my team's documents," "only during working hours." These depend on properties attached to the data, and something like row-level security, which applies access rules per row, covers that ground.
- Organizations full of exceptions — create a role per exception and the count climbs fast. Once roles exist for one marketing lead or for contract interns specifically, the device has stopped providing value. The usual fix is refusing the exception rather than encoding it, which is a conversation rather than a configuration change.
- Permissions needed briefly — two hours of database access during an incident. Handle it by attaching and detaching a role and the detaching gets forgotten. A separate time-bounded grant works better, because expiry is the only mechanism that doesn't depend on somebody remembering.
One more limit. Roles built to match the org chart have to be rebuilt at every reorganization. Build them from the work rather than from team names and they survive, because the work a company does changes more slowly than the boxes it draws around the people doing it.
How it sounds at work
"You listed permissions by screen. They have to be split by action."
Multiple actions in one cell make least privilege impossible.
"Twenty people have the administrator role. That's not a role any more, it's the default."
The role design isn't reflecting actual job functions.
"Don't grant incident access as a role. Issue it for two hours."
Avoiding an approach where the removal gets forgotten.
At Pagedeck, Theo keeps five roles and manages twenty-two permissions as a table. The table lives in the same repository as the code, and Grace reviews changes to any cell. Headcount per role gets pulled each quarter; last quarter eleven people held the administrator role, and six of them had no need to see billing details and were moved down to editor.
What people get wrong
The most common mistake is reading it as solving the permission problem. It's a device for handling permissions, so the expectation is natural. But what this method settles is only the rule for who may do what; checking that rule on each actual request is separate work. A document opening for anyone who knows the share link is a case where login passed and no permission check sat at that point. Build the role table carefully and a newly added endpoint that never reads it is wide open regardless. The table is a specification; enforcement is a separate piece of work that has to happen at every entrance.
Believing that hiding a button equals blocking a permission is the other one. If the user can't see it, they can't press it — the arithmetic sounds fine. But a screen is one of several ways to send a request. Knowing the endpoint address is enough to call it directly, and a hidden button has no bearing on that call. The check belongs on the receiving side, and hiding buttons counts only as convenience that reduces mistaken clicks. Treating it as the control is how permission bugs survive a review that only looked at screens.
Where to go next
- Application security
see which family this method belongs to
- Authentication
read the step that asks first, at the door
Related terms
Last updated 2026-09-26