Banking Authorization with OpenFGA
Banking and fintech authorization isn't just "who can read this record?" — it's "who can move how much money out of which account, and who approved that delegation?". A relationship-based model captures the answer without scattering the rules across application code.
The full working model is in openfga/sample-stores/stores/banking.
Core resources and relations
- organization — the bank tenant.
- account — has an
owner, optionalco_owners, and anaccount_managerassigned by the bank. - transaction — initiated against an
account, subject to a per-actor amount limit.
The interesting relations:
ownerandco_owneronaccount— full read and full transaction rights up to a personal limit.account_manageronaccount— bank staff who can view the account and initiate transactions, but only up to a manager-specific limit that may differ from the owner's.delegateonaccount— owners can delegate a subset of rights to another person (a spouse, a bookkeeper) with a separate, lower limit.
Why this is hard in role-only systems
A typical "manager", "owner", "delegate" RBAC scheme answers what action is allowed but not up to what amount. Hard-coding the amount in application logic means:
- The auth decision is split across two systems (an RBAC check + an
if amount > Xbranch). - Audit can't answer "who could have wired more than $50k from account A on date D" without joining application code with role tables.
- Delegation expiry, per-transaction overrides, and dual-control approvals each become bespoke features.
OpenFGA expresses the limit as part of the relationship using conditions, so the check can_initiate_transfer takes the transaction amount as a contextual parameter and returns a single allow/deny.
Where this maps to OpenFGA features
| Banking requirement | OpenFGA feature |
|---|---|
| Per-actor transaction limits | conditions on can_initiate_transfer |
| Owner / co-owner / delegate roles | direct relations on account |
| Delegated authority (bookkeeper) | userset relations + condition on amount |
| Time-bounded delegation | contextual tuples carrying expiry |
| Tenant isolation per bank brand | tenant-scoped types, see multi-tenant SaaS |
| Audit who-could-have-done-what | Read Changes API |
Common extensions
The base sample covers individual accounts. Adopters typically extend it with:
- Joint accounts and trusts. Add a
beneficiaryrelation that grants read access only. - Corporate accounts. Introduce a
companytype; assign signatories viasignatoryand require N-of-M via your application callingCheckfor each required signer. - Step-up authentication. When the transaction amount exceeds a threshold, pass a contextual tuple
mfa_verified=trueand gate the relevant relation on it.
Working sample
The schema, sample tuples, and assertions are in openfga/sample-stores/stores/banking. For the broader pattern of "permissions plus runtime context", see Modeling ABAC and Contextual and Time-Based Authorization.