Understand how Oso uses facts
Every authorization decision in Oso combines:- Your policy (written in Polar): the logic that defines who can do what.
- Facts: the current state of your application that the policy uses to decide.
- Centralized facts in Oso Cloud.
- Context facts sent with the request.
- Local facts queried from your application database (if using Local Authorization).
- Check API: performs authorization decisions using data stored in your centralized authorization data store. Available via CLI and SDKs for Node, Python, Go, Java, Ruby, and .NET.
- Local Check API: performs checks using your local facts while still considering centralized authorization data. See Local Authorization for details.
Know the fact structure
A fact has:- Name (predicate) — usually in
verb_object
form for readability, e.g.has_role
,has_relation
,is_public
. - Arguments — 1-5 arguments, each either:
- A typed ID reference to an application object:
User{"alice"}
. - A literal value:
"admin"
,42
.
- A typed ID reference to an application object:
Choose where to store facts
Data Type | Storage Recommendation |
---|---|
Affects multiple services | Store in Oso Cloud. |
Single-service only | Keep in your application DB. |
Changes frequently | Keep in your application DB. |
High cardinality (e.g. millions of files) | Keep in your application DB. |
Global attributes (e.g. is_superadmin , is_banned ) | Store in Oso Cloud. |
Ephemeral/request-specific (e.g. IP, time of day) | Send as context facts. |
Centralize shared facts in Oso Cloud
Centralized facts are optimized for authorization lookups and can be faster than application DB queries.When to centralize
- Organization/resource roles:
has_role(User, "admin", Organization)
. - Global flags:
is_superadmin(User)
,is_banned(User)
.
Manage facts with the API
Action | API Names | Notes |
---|---|---|
Transaction | batch , bulk | Atomic inserts/deletes (recommended). |
Write | insert , tell | Add facts. |
Delete | delete | Remove facts. |
Read | get | Fetch centralized facts (no inference). |
Pass context facts for request-specific data
Context facts exist only for the duration of a request. Use them for:- External data (e.g. IDP token claims).
- Ephemeral attributes (e.g.
is_weekend
,request_came_from_eu
).
Reference facts in Polar policies
Validate and declare fact types
Oso infers fact types from policy usage:are_friends(User, Dog)
will be accepted.
Invalid facts (wrong type, missing args, misspelled predicates) are rejected.
Declare unused types explicitly:
Keep facts in sync
Keep centralized facts in sync with your application database:- Insert: When adding roles, relationships, or attributes.
- Delete: When removing them.
- Bulk operations: For initial loads or periodic sync.
- Use transactional APIs (
batch
,bulk
) to apply multiple changes atomically.
- Invite collaborator →
insert has_role(User{"coder"}, "collaborator", Repo{"anvils"})
. - User leaves org →
delete has_role(User{"alice"}, "member", Org{"acme"})
.
Facts in different authorization models
Facts can represent:- RBAC. Role assignments:
has_role(User, "admin", Org)
. - ABAC. Attributes:
has_department(User, "engineering")
. - ReBAC. Relationships:
has_relation(Document, "folder", Folder)
.