Executive summary
Authentication answers who the user is. Authorization answers what that user can do, in which tenant, over which resource, in which state and through which path. In multi-tenant systems, that difference defines the boundary between legitimate operation and data leakage.
The main invariant
The central invariant is simple: sensitive business data must not be queried without explicit tenant context or an equivalent policy boundary. If the tenant is absent, the action should fail closed.
Ownership is not always a user. It may belong to a tenant, project, team, service account, contract or workflow state. Policy must represent these relationships instead of spreading local conditions across controllers.
Action and resource
Broad roles such as admin or user are not enough. The final decision should consider action and resource: read, list, export, edit, approve, cancel, invite and delete are different operations with different impact.
Validating isolation beyond the happy path
The happy path only proves that the system works for authorized users. Security requires proving that unauthorized users are denied consistently across detail, listing, search, export, cache, jobs and integrations.
- Create similar resources in different tenants.
- Attempt cross-tenant access by direct identifier.
- Test listing and search with a user outside the scope.
- Validate export with a read-only profile.
- Run a job after revoking the original permission.
- Confirm cache does not return data from another context.
- Review error messages to avoid resource enumeration.
Permissions need review with real usage
Permissions accumulate debt. Temporary roles become permanent, service accounts gain broad scopes and users change functions without losing old access. Periodic review should compare granted permission, recent usage and current need.
This review is especially important for service accounts, integrations and administrative roles because they often operate away from the main interface.
Conclusion
Multi-tenant authorization is a system property. It requires invariants, centralized policy, contextual cache, jobs with revalidation, negative tests and observability. The goal is to make correct access natural and incorrect access consistently impossible.