04 — Authorization & RBAC

Deciding what an authenticated principal may do. Layered RBAC + ABAC + ReBAC via a deny-by-default policy engine (Cedar + ReBAC, ADR-0010). Closes OWASP API1 (BOLA), API3 (BOPLA), API5 (BFLA) — three of the top five API risks.


1. The model: PEP → PDP, deny-by-default

flowchart LR
    classDef e fill:#fde68a,stroke:#b45309,color:#111827;
    classDef p fill:#bbf7d0,stroke:#15803d,color:#111827;
    classDef d fill:#c7d2fe,stroke:#3730a3,color:#111827;
    req["request"]:::e --> pep["PEP (gateway/service): intercept every access"]:::e
    pep --> pdp["PDP: Cedar evaluate(principal, action, resource, context)"]:::p
    rebac["ReBAC graph (sharing/membership)"]:::d --> pdp
    rbac["RBAC roles"]:::d --> pdp
    abac["ABAC attrs: tags, classification, residency"]:::d --> pdp
    pdp --> dec{"permit / forbid (deny-by-default)"}:::p
    dec -->|permit + obligations| act["allow (+ watermark/log/step-up)"]:::e
    dec -->|forbid| block["403"]:::e

2. RBAC roles

Scope Roles
Tenant / Org owner · admin · member · billing · auditor (read-only audit)
Resource (via ReBAC) owner · editor · commenter · viewer
Machine service-account roles + API-key scopes (subset of the principal’s rights)

Roles grant capabilities; a principal’s effective permission = role capabilities ∪ ReBAC grants ∩ API-key scope, evaluated by Cedar. Separation of duties: e.g. an auditor reads the audit log but cannot mutate data; billing can’t read files.


3. Closing the top API authZ risks

Risk The failure BitVault control
API1 BOLA (#1) endpoint returns object X for ID supplied by client without checking ownership every object access → PDP check (principal, action, this resource) and RLS (05); never trust a client-supplied node_id/share_id
API3 BOPLA API exposes/accepts fields the role shouldn’t (excessive exposure / mass assignment) field-level authz; explicit allow-listed DTOs; never bind raw request bodies to models
API5 BFLA a member calls an admin function function-level role checks, deny-by-default; admin routes gated + audited

BOLA is the #1 API risk (~40% of attacks) precisely because it’s easy to check “is the user logged in?” and forget “does this user own this object?”. The PDP makes object-level authz the default path, not an afterthought.


4. Scopes & least privilege for machines

API keys / service accounts carry scopes (OAuth-style: files:read, files:write, shares:create, scoped to resource prefixes). A key’s scope is a subset of its principal’s rights — it can never exceed them, and defaults to minimal (02, ADR-0035).


5. Privilege-escalation prevention


6. Public sharing authorization

A public share/presigned token is a capability: the PDP treats the anonymous principal as authorized for exactly the shared node + permission + window — nothing else (06).


7. Threats addressed & residual

Threat Control Residual
Cross-object / cross-tenant access (BOLA) PDP object-authz + RLS low (defense in depth)
Excessive data exposure / mass assignment DTO allow-lists + field authz low
Privilege escalation deny-by-default + authorized role changes low
Policy bug / misgrant policy simulation (“prove no public read of /legal”, product/07) + CI policy tests low-med

References