Skip to content
All insights

Permissions belong on the server

A role name is only a label; protect each resource at every trusted boundary and test what each person is allowed to do.

Security. 24 October 2026. 3 min read.

Role-based access control is often introduced as a list of job titles: cashier, supervisor, manager, administrator. The list is only the vocabulary. The security decision is whether this person may perform this action on this resource, in this organization, under these conditions. A hidden button can make an interface easier to use; it cannot make that decision safely on its own.

Start with the action

Write down the actions people perform before creating roles. Reading a record, exporting it, approving it, changing it, and deleting it are different permissions. A role should be a named set of those permissions, not a shortcut that quietly grants every action in a module.

  • Name actions as verbs: view, create, edit, approve, export, or delete.
  • Keep sensitive actions separate. Permission to view a payment is not permission to refund it.
  • Document which roles need each action and why, including actions that nobody should perform.

Scope the resource before checking access

In a multi-organization system, permission to edit an invoice is not enough. The invoice must also belong to an organization the user can access. Resolve the resource on the server, check its scope, and then check the action. Do not trust an organization id or record id just because it arrived in a URL, form, or client-side state.

Illustrative pseudocode for one authorization decision
function can(user, action, resource) {
  const inScope = user.organizationId === resource.organizationId;
  const allowed = permissionMatrix[user.role]?.has(action) === true;
  return inScope && allowed;
}

This is a teaching example, not a production implementation. Real checks also account for the resource's current state and any policy specific to the operation. The useful property is that scope and action are both explicit.

Enforce access at the trusted boundary

The server must check access wherever protected data can be read or changed: API handlers, server actions, background jobs, exports, and administrative operations. The interface can hide an unavailable control to reduce confusion, but a direct request must receive the same authorization check. Otherwise a user can skip the interface and call the endpoint themselves.

Test the denied paths too

A permissions matrix is a useful design document, but it is not proof that the application follows it. Turn the matrix into tests for allowed and denied actions. Include a user from another organization, an unauthenticated request, a stale role, and a resource whose state no longer permits the operation. Tests should exercise the same server boundary a real request uses.

The negative cases matter because access-control failures often come from an omitted check or a resource lookup with the wrong scope. A test that proves one manager can approve an item does not prove that a cashier, a different organization, or an expired session cannot.

Make decisions explainable

For sensitive operations, record enough context to answer who acted, what action they requested, which resource was involved, when the decision happened, and whether it was allowed. Keep credentials and secrets out of audit records. An audit trail should help an operator explain a decision without exposing data that is not needed for that explanation.

  1. List the resources and actions the system protects.
  2. Map roles to the minimum actions each role needs.
  3. Include organization or ownership scope in the server-side check.
  4. Exercise both permitted and denied requests in automated tests.
  5. Review access changes and sensitive decisions through an appropriate audit trail.

Roles help people understand a system. Server-side policy is what protects it. Keeping those jobs separate makes permissions easier to review, test, and change as the work changes.

Related articles

Talk through the problem.

Tell us about the workflow, integration, or data move you are planning.

Start a project

Custom enterprise systems