Architecture

Designing Role-Based Access Control That Scales

Updated May 18, 2021By the CalliArc team

Key takeaway

Assign permissions to roles and roles to users — never permissions directly to users. Enforce every check in one central place against the authenticated identity, and make "can this user act on this specific record?" a single function, because scattered authorization checks are where broken access control comes from.

Permissions start simple — admin and user — and then a customer asks for a read-only accountant, a regional manager, and an auditor who can see everything but change nothing. How you modelled it in week two determines whether that's an afternoon or a quarter.

Get the model right

  • Define fine-grained permissions (invoice.read, invoice.approve), group them into roles, and assign roles to users. Checking a permission rather than a role name is what lets you add roles without touching code.
  • Allow multiple roles per user; real organisations don't fit one label.
  • Scope roles to a context — an organisation, a project, a region — because the same person is often an admin in one place and a viewer in another.
  • Keep permission names stable and explicit; they will end up in customer documentation and security questionnaires.

Roles alone won't cover everything

Most real requirements include rules about the specific record: a manager approves expenses only for their own team, a doctor sees only their own patients, a user edits only their own drafts. Handle these as attribute-based rules layered on top of roles, evaluated in the same place. The question to answer is always "can this identity perform this action on this resource?" — not "is this user an admin?".

One enforcement point

  • Put authorization in a single service or middleware layer that every request passes through. Checks scattered across controllers and templates are how one endpoint ends up unprotected.
  • Derive identity and scope from the authenticated session — never from an id supplied by the client.
  • Default deny. New endpoints should be inaccessible until explicitly permitted.
  • Enforce on the API, not in the interface. Hiding a button is presentation, not security.
  • Write tests that assert each role cannot do what it shouldn't — negative tests catch far more than positive ones here.

Operational details that matter later

  • Log every permission grant and revocation; auditors will ask, and so will you during an incident.
  • Support time-bounded elevation for support staff who occasionally need more access, rather than permanently granting it.
  • Plan for delegation — customers will want to manage their own users' roles without contacting you.
  • Review role assignments periodically; access accumulates as people change jobs and nobody removes the old grants.
Share LinkedIn X

Ready to build it right?

Get a transparent, milestone-based estimate for your project in a free consultation.

Book a free strategy call