Fine-grained authorization answers a narrower question than authentication: not who are you, but may you perform this action on this resource now? RBAC groups permissions into stable business roles; ABAC adds resource and context rules such as tenant, ownership, data classification, geography, time window, or workflow state. In practice, robust systems usually combine both.
This approach must be enforced at the business boundary, not only in the UI or at the edge. Hidden buttons are not authorization, and a gateway-only check is insufficient if internal services or data stores can still be reached through other paths.
How It Works
- Define protected resources and actions explicitly, for example
invoice:read,invoice:approve,salary:update, not just “access this endpoint”. - Use RBAC for stable job-function entitlements and ABAC for constraints that depend on subject, resource, or environment attributes.
- Evaluate authorization for every protected operation and constrain the downstream query or command with the same policy decision so that record filtering matches the allow/deny result.
- Fail closed: if the policy is missing, an attribute cannot be resolved, or the policy engine is unavailable, the protected action is denied.
- Version policies, assign each decision a policy identifier, and log subject, action, resource, result, and reason so denials and overrides are explainable.
Failure Modes
- Authorization is enforced only in the UI or API gateway, while internal services or direct data paths bypass the same policy.
- RBAC becomes a large set of special-case roles, or ABAC rules are scattered in application code, producing inconsistent semantics between services.
- Attribute freshness is not controlled, so stale tenant, employment, or approval-state data causes over-permit or over-deny decisions.
- The API decision says “allowed”, but the underlying query is not filtered by tenant or ownership, leaking other records through direct object references.
- Policy evaluation fails open under timeout or dependency failure, turning a control-plane outage into unauthorized access.
Verification
- Coverage: 100% of non-public business operations have explicit authorization tests with at least one allow case and one deny case in CI.
- Isolation: in security tests, 100% of cross-tenant and out-of-scope record-access attempts are denied, and no forbidden record fields are returned in error payloads or partial responses.
- Revocation and policy propagation: critical role revocations take effect within the required window (for example <= 60 s), and centrally managed policy updates reach all enforcement points within the agreed window (for example <= 15 min).
- Decision latency: p95 authorization evaluation stays within the allocated request budget (for example <= 20 ms local, or <= 75 ms including remote policy and attribute calls) under representative load.
- Fail-closed drill: disconnect the policy engine or an authoritative attribute source and verify protected operations deny rather than allow, with an alert and audit entry for each failure mode.
- Audit completeness: 100% of denied requests and privileged grants include subject, action, resource identifier, policy identifier, result, and timestamp in searchable logs.
Variants, Related Tactics, and References
- RBAC-only is the simpler variant: sufficient when the permission model is stable, the number of roles is manageable, and context does not materially change access decisions.
- Relationship-Based Access Control (ReBAC), as pioneered by Google Zanzibar, models authorization as graph relationships (owner-of, member-of, viewer-of) and evaluates access by traversing the graph — well suited for document sharing and social-graph-style permissions.
- Policy-as-code engines (Open Policy Agent/Rego, AWS Cedar, Casbin) externalize authorization logic from application code into declarative, testable, versionable policies.
- Least Privilege is the design principle that fine-grained authorization implements: every actor gets only the permissions required for its function.
- Strong Authentication (MFA / OIDC) provides the verified identity that authorization decisions depend on — authorization is only as trustworthy as the identity signal it receives.
- Input Sanitization / Output Encoding reduces injection paths that can subvert authorization-sensitive query logic, but it does not replace object-level authorization checks.
References:
- NIST Model for Role-Based Access Control: Toward a Unified Standard
- NIST SP 800-162: Guide to Attribute Based Access Control (ABAC) Definition and Considerations
- OWASP Authorization Cheat Sheet
- Zanzibar: Google’s Consistent, Global Authorization System
- Software Architecture in Practice — Bass, Clements & Kazman (full citation)