2. Permissions never live in tokens
Tokens identify the user, org, IdP and groups only.
Context
Putting roles or permissions in JWT scopes is common and cheap to check, but tokens outlive changes (a revoked manager keeps approving until expiry), grow with every permission, tie authorization to one IdP, and cannot carry scope (which team, which units).
Decision
Tokens identify the user, org, IdP and groups only. Grants are loaded from the access schema per request (cached with generation-based invalidation and Postgres NOTIFY) and sent to Cerbos.
Consequences
- Revocation is effective within seconds.
- Any IdP works: the product's auth layer builds the
Subject. Group mappings turn IdP groups into roles without the IdP knowing about permissions. - Each request costs a cache lookup (and a store read on a miss) plus a Cerbos call; the route guard (
HasPermission) needs no Cerbos call.
1. Cerbos evaluates generated policies; grants travel as principal attributes
Cerbos PDP (Apache 2.0, pinned to 0.57.0) runs as a sidecar.
3. `resource:action` keys; scope lives on the assignment
Permission keys are resource:action, split on the first colon (actions may contain colons, as in read:reason for field-level permissions).