Today’s Lesson
Security for Legal SaaS — Episode 24: ABAC and Policy Engines
When Roles Are Not Enough
In Episode 23, we built a role-based access control model with five or six roles: Firm Admin, Partner, Associate, Paralegal, Client Viewer. That covers 80% of access decisions. This episode is about the other 20% — the decisions where a role alone doesn't carry enough information.
Consider this scenario: an associate in the M&A practice group needs access to M&A matter documents during business hours from the firm's network. RBAC can tell you they're an associate. It cannot tell you they're in M&A, that the document is tagged as M&A, that it's currently 2pm on a Tuesday, or that they're connecting from the office VPN. For those decisions, you need Attribute-Based Access Control — ABAC.
What Is ABAC?
ABAC makes access decisions based on attributes — properties of the user, the resource, the action, and the environment. Instead of a static role-to-permission mapping, ABAC evaluates a policy that considers multiple attributes at decision time.1
The four attribute categories:
| Category | Examples in Legal SaaS |
|---|---|
| Subject attributes | User's role, department, practice group, seniority, bar admission status |
| Resource attributes | Matter type (litigation, M&A, IP), confidentiality level, client name, jurisdiction |
| Action attributes | Read, write, delete, export, share externally |
| Environment attributes | Time of day, network location (office VPN vs. public wifi), device compliance status |
An ABAC policy combines these attributes into rules:
Allow if subject.department = "M&A" AND resource.matter_type = "M&A" AND action = "read" AND environment.time is within business_hours
This is fundamentally more expressive than RBAC. A single ABAC policy can encode what would require dozens of purpose-built roles.2
RBAC + ABAC: The Practical Approach
Pure ABAC — replacing all roles with attribute policies — is theoretically elegant but operationally complex. Most real-world systems use a hybrid approach:3
- RBAC for broad strokes: Roles define the general permission level (Admin, Associate, Viewer)
- ABAC for fine-grained decisions: Attributes refine access within a role (which matters, which document types, under what conditions)
In a legal SaaS platform, this looks like:
- RBAC determines: "Associates can access matter documents"
- ABAC refines: "Associates in the litigation department can access litigation matter documents marked Confidential, during business hours, from managed devices"
The role gets the user through the first gate. The attributes decide exactly which resources they can touch and under what conditions.
Policy Engines: Externalising Access Decisions
Hardcoding access rules in application code — `if (user.role === 'admin' || (user.role === 'associate' && matter.department === user.department))` — works for simple cases but becomes unmaintainable as rules multiply. Policy engines solve this by externalising access decisions into a dedicated service that your application queries at runtime.4
Open Policy Agent (OPA)
Open Policy Agent is the most widely adopted general-purpose policy engine, donated to the Cloud Native Computing Foundation (CNCF) and graduated in 2021.5 Policies are written in Rego, a declarative query language:
allow if {
input.user.role == "associate"
input.user.department == input.resource.practice_group
input.action == "read"
}
OPA runs as a sidecar service alongside your application. When a user requests access to a resource, your application sends the relevant attributes to OPA, and OPA returns an allow/deny decision. The application never evaluates the policy itself — it delegates entirely to OPA.5
Strengths: Language-agnostic (works with any backend), extensive ecosystem, Kubernetes-native, well-tested in production at large scale.
Tradeoffs: Rego has a learning curve. Policies are powerful but can become complex. Performance requires careful policy design at high query volumes.
AWS Cedar
Cedar is AWS's purpose-built authorisation policy language and engine, open-sourced in 2023 and used in production by Amazon Verified Permissions.6 Cedar was explicitly designed for application-level authorisation — it's more specialised than OPA's general-purpose approach:
permit(
principal in Role::"associate",
action == Action::"readDocument",
resource in MatterGroup::"litigation"
) when {
principal.department == resource.practiceGroup
};
Strengths: Formal verification — Cedar's type system can mathematically prove that certain policy configurations are correct. Designed specifically for RBAC + ABAC hybrid models. Simpler syntax than Rego for authorisation-specific use cases.
Tradeoffs: Narrower scope than OPA (authorisation only, not general policy). Newer ecosystem with fewer community integrations.
Google Zanzibar / OpenFGA
Zanzibar is Google's internal authorisation system, handling trillions of access checks per second for Google Drive, YouTube, and Google Cloud.7 OpenFGA is the open-source implementation. Unlike OPA and Cedar, Zanzibar uses a relationship-based model — access is determined by the relationships between users and resources (e.g., "Alice is an editor of Document X" or "Alice is a member of Team Y which owns Matter Z").8
Strengths: Exceptional performance at scale. Natural fit for document sharing and collaboration models. Strong consistency guarantees.
Tradeoffs: The relationship model is different from traditional RBAC/ABAC thinking — requires rethinking how you model access.
Comparison summary from AWS and Teleport security benchmarks: OPA is best for general-purpose policy across infrastructure and applications. Cedar excels at application-level authorisation with formal verification. Zanzibar/OpenFGA is optimal for relationship-heavy models like document sharing.9
Performance: Policy Evaluation at Scale
Legal SaaS platforms evaluate authorisation decisions on every API request — potentially thousands per second during peak usage. Policy engine performance is a real concern:10
| Consideration | Guidance |
|---|---|
| Caching | Cache policy decisions for identical inputs (same user, same resource, same action). Invalidate on role changes |
| Data locality | Keep frequently-used attributes (user role, matter assignments) in the policy engine's data store, not fetched per-request from a remote database |
| Policy complexity | Simpler policies evaluate faster. Avoid deeply nested conditions or external data calls in hot paths |
| Bulk evaluation | When loading a matter list, evaluate access for all matters in one batch call rather than one-per-matter |
A well-configured OPA instance can evaluate policies in sub-millisecond time for typical authorisation queries. Cedar was benchmarked by AWS at similar performance. The overhead of a policy engine call is negligible compared to a database query.56
Legal Context: Where ABAC Shines
Several legal SaaS scenarios specifically require attribute-based policies:
Matter-based access: An associate should only access matters they're assigned to. The assignment is an attribute of the relationship between user and matter — not a role.
Jurisdiction restrictions: A document produced under Australian privacy law may require that only users admitted to practice in Australia (a subject attribute) can access it.
Time-limited access: A contract review team gets access to due diligence documents for 90 days. After the deal closes, access automatically expires based on an environment attribute (current date vs. access expiry).
Confidentiality tiers: Documents classified as "Attorney Eyes Only" require both the correct role (attorney) and the correct matter assignment. Documents at "Highly Confidential" require an additional approval attribute.
Export controls: Downloading or sharing documents externally may require approval from a supervising partner — an action that changes the user's attributes for that specific resource.
The AuthZEN Standard
The industry is converging on standardised interfaces for policy engines. AuthZEN, an OpenID Foundation working group, is developing a standard API for authorisation — a single interface that works regardless of whether the backend is OPA, Cedar, OpenFGA, or a custom engine.11 For legal SaaS builders, this means you can adopt a policy engine today without permanent vendor lock-in.
What's Next
Episode 25 covers Ethical Walls and Matter-Scoped Access — the legal profession's specific access control requirement where two partners in the same firm may be on opposite sides of the same deal, and your software must enforce the barrier.
Sources & Further Reading
Sources & references
- NIST, SP 800-162: Guide to Attribute Based Access Control (ABAC) — the NIST ABAC standard.
- CNCF, Love, Hate, and Policy Languages: An Introduction to Decision-Making Engines — comparison of policy approaches (May 2024).
- Oso, OPA vs Cedar vs Zanzibar: 2025 Policy Engine Guide — comparative analysis of leading policy engines.
- Permit.io, Policy Engines: Open Policy Agent vs AWS Cedar vs Google Zanzibar — architectural comparison.
- Open Policy Agent, OPA Documentation — official OPA documentation and Rego language reference.
- AWS, Cedar Policy Language — Cedar documentation and formal verification details.
- Google Research, Zanzibar: Google's Consistent, Global Authorization System — original Zanzibar paper (2019).
- OpenFGA, OpenFGA Documentation — open-source Zanzibar implementation.
- Teleport, Security Benchmarking Authorization Policy Engines — comparative security analysis of Rego, Cedar, and OpenFGA.
- Auth0, Understanding ReBAC and ABAC Through OpenFGA and Cedar — relationship-based vs. attribute-based models.
- Nordic APIs, AuthZEN: A New Standard for Fine-Grained Authorization — the emerging authorisation API standard.