Deny-Wins Semantics
An authorization evaluation rule where an explicit deny on any matching permission overrides all allow permissions. Used to enforce least-privilege without restructuring role hierarchies.
Deny-wins (also called "deny overrides" or "explicit deny") is an authorization evaluation strategy where an explicit effect: "deny" on any matching permission overrides all effect: "allow" permissions, regardless of how many allow permissions match.
Why deny-wins?
The alternative is "allow-wins" or "first-match" evaluation. These approaches require careful ordering of permissions and make it difficult to enforce restrictions without restructuring role hierarchies.
With deny-wins semantics, you can grant broad access via one role ("billing-admin: invoice:*") and then add a restriction role ("restricted: invoice:delete → deny") to override the broad grant. No role restructuring required.
Example
User has two roles:
Role "billing-admin": invoice:* → allow (matches invoice:delete)
Role "restricted": invoice:delete → deny
Evaluation: does user have invoice:delete?
Matching permissions:
1. invoice:* → allow ✓ matches
2. invoice:delete → deny ✓ matches
Result: DENY (deny-wins — any explicit deny overrides all allows)Compliance use case
Deny-wins is particularly valuable for compliance scenarios. Suppose a user is under investigation and should be prevented from deleting records, but you don't want to restructure all their roles. Add a "deny-delete" policy and the restriction takes immediate effect across all resources.
WardenAuth's implementation
WardenAuth uses deny-wins semantics by default. The evaluation algorithm:
- Collect all permissions from all of the subject's roles that match the requested resource + action (including wildcards)
- If any matching permission has
effect: "deny"→ return DENIED - If any matching permission has
effect: "allow"→ return ALLOWED - Otherwise → return DENIED (no matching permission)
Related terms
Authorization that evaluates permissions at the individual resource or action level, rather than broadly by user type or role.
A binding between a subject (user or service) and one or more roles within a scope. Defines what the subject can do in that tenant context.
A permission where the resource or action component is *, matching any value. For example, invoice:* grants all actions on invoices; *:read grants read on all resources.