Authorization-Aware Data Access
Checking one resource is easy: check(user, view, document:42). Listing resources is not: "show the 50 most recent documents this user can see" cannot be answered by fetching every document and checking each one. Authorization has to shape the query itself.
Strategies
Rendering diagram…
Diagram source
flowchart TB
q([List documents for alice]) --> choice{Strategy}
choice --> filter[Query-time filter]
choice --> lookup[Lookup from engine]
choice --> materialized[Materialized access set]
filter -->|"policy compiled to a WHERE clause"| db1[(Product database)]
lookup -->|"engine returns allowed IDs, then fetch"| db2[(Product database)]
materialized -->|"join against precomputed user-resource table"| db3[(Product database)]
| Strategy | How it works | Fits when | Trade-off |
|---|---|---|---|
| Query-time filter | Policy is translated into a database condition, for example organization and team membership. Row-level security can enforce it. | Rules are simple and live in the same database as the data. | Complex relationship rules do not translate well into SQL. |
| Lookup from the engine | The engine lists resource IDs the actor can access; the application fetches those. | Relationship engine in use, moderate result sizes. | Very large access sets are slow to transfer and page through. |
| Materialized access set | A table of actor-to-resource access, updated from relationship changes, joined in queries. | Large datasets with sorting, search, and pagination. | Storage and write amplification; must be kept consistent. |
| Check after fetch | Fetch a page, check each item, fetch more if needed. | Small datasets or rare denials. | Unpredictable latency when many items are denied. |
Search and Pagination
Rendering diagram…
Diagram source
sequenceDiagram autonumber participant A as Application participant E as Policy engine participant S as Search index A->>E: Which teams and folders can alice access? E-->>A: Access principals: team:design, folder:brand, user:alice A->>S: Search "logo" filtered by access principals, page 1 S-->>A: 20 results, all visible to alice
For search, indexes store the access principals of each document (owner, teams, parent folders) and filter on them. The engine supplies the actor's principals once per query, not one check per result.
Watch For
- Counts leak information. "37 results" computed before filtering reveals that hidden documents exist.
- Stale access sets. Materialized and indexed access must update when relationships change; otherwise revoked users keep seeing items in lists.
- Two enforcement points. If lists use a filter and detail pages use the engine, both must agree. Test them against the same table of expected decisions.