Fine-Grained Authorization (FGA)
Auris FGA is a Zanzibar-style relationship-based authorization (ReBAC) engine for object-level access control. While RBAC answers “does this user have the view:invoices permission globally?”, FGA answers “does this user have the viewer relation on document #123 specifically?”.
FGA is the right tool when authorization depends on relationships between specific objects — not just user roles.
Common use cases:
- A document sharing system where each document has individual owners, editors, and viewers
- A multi-tenant SaaS where access to a project depends on organization membership
- A file system where a folder’s permissions are inherited by its contents
- A B2B portal where customer contacts can only see their own organization’s data
FGA replaces Ory Keto as Auris’s ReBAC layer. Set FGA_ENGINE_ENABLED=true in the API environment to activate FGA. When false, the system falls back to Keto (deprecated).
Core Concepts
Objects
An object is an entity in your system identified by a type and an ID, written as type:id. Examples:
document:inv-2024-001folder:invoices-q4project:website-redesignorganization:acme-corp
Relations
A relation describes how a subject is connected to an object. Relations are defined in the authorization model. Examples: owner, editor, viewer, member, admin.
Subjects
A subject is the entity being authorized. Subjects are also written as type:id. The most common subject type is user. Subjects can also be sets — organization:acme-corp#member means “anyone who is a member of the acme-corp organization”.
Tuples
A relationship tuple is a stored fact: (objectType, objectId, relation, subjectType, subjectId). For example: “user:alice is a viewer of document:report-2024” is stored as:
{
"objectType": "document",
"objectId": "report-2024",
"relation": "viewer",
"subjectType": "user",
"subjectId": "alice"
}Authorization Models
The authorization model is a schema written in an OpenFGA-compatible DSL. It defines what types exist and what relations each type supports.
DSL Syntax
type user
type organization
relations
define admin: [user]
define member: [user] or admin
type project
relations
define org: [organization]
define admin: [user] or admin from org
define editor: [user] or admin
define viewer: [user] or editor
type document
relations
define project: [project]
define owner: [user]
define editor: [user] or owner or editor from project
define viewer: [user] or editor or viewer from project or member from org of projectThis model defines:
- Any user can be a
memberoradminof an organization - A project belongs to an organization; project admins inherit from org admins
- A document belongs to a project; its viewer set includes direct viewers, editors, project viewers, and org members
Rewrite Types
Auris FGA supports 6 rewrite types for computing relation membership:
| Type | Description | DSL Syntax |
|---|---|---|
this | Direct tuple lookup | [user] |
computedUserset | Members of another relation on the same object | or owner |
tupleToUserset | Follow a relation to another object, then get its relation | viewer from project |
union | Users in any of the operands | [user] or owner |
intersection | Users in all operands | [user] and verified |
exclusion | Users in the left operand but not the right | [user] but not blocked |
Creating and Activating a Model
/api/fga/modelsRequires: manage:fga_modelsCreate a new authorization model version. Body: { name: string, dsl: string }. Auris parses and validates the DSL before storing.
/api/fga/models/:id/activateRequires: manage:fga_modelsActivate a model version. Only one model can be active at a time. Activating a new model does not invalidate existing tuples.
Writing Tuples
Tuples are the runtime data — the actual relationships between objects and subjects in your application.
/api/fga/tuplesRequires: manage:fga_tuplesWrite one or more relationship tuples. Body: { writes: TupleInput[] }. Each tuple: { objectType, objectId, relation, subjectType, subjectId, subjectRelation? }.
/api/fga/tuplesRequires: manage:fga_tuplesDelete one or more relationship tuples. Body: { deletes: TupleInput[] }.
/api/fga/tuples/bulkRequires: manage:fga_tuplesWrite and delete tuples in a single atomic request. Body: { writes: TupleInput[], deletes: TupleInput[] }. Maximum 100 operations per request.
// Share a document with a user (write a tuple)
await fetch('/api/fga/tuples', {
method: 'POST',
headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
writes: [
{
objectType: 'document',
objectId: 'report-2024',
relation: 'viewer',
subjectType: 'user',
subjectId: 'bob',
},
],
}),
})
// Revoke access (delete a tuple)
await fetch('/api/fga/tuples', {
method: 'DELETE',
headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
deletes: [
{
objectType: 'document',
objectId: 'report-2024',
relation: 'viewer',
subjectType: 'user',
subjectId: 'bob',
},
],
}),
})Checking Authorization
Check
The check endpoint answers “does subject X have relation R on object Y?”
/api/fga/checkEvaluate whether a subject has a relation on an object. Returns { allowed: boolean }. No authentication required — uses the caller’s identity from the access token unless an explicit subject is provided.
Expand
The expand endpoint returns the full set of subjects that have a given relation on an object, useful for debugging and building user-facing sharing panels.
/api/fga/expandRequires: view:fga_tuplesExpand a relation to show all subjects (with resolution path). Body: { objectType, objectId, relation }.
List Objects
The list-objects endpoint returns all objects of a given type that a subject has a specified relation to — useful for filtering query results.
/api/fga/list-objectsRequires: view:fga_tuplesList all objects where the subject has the given relation. Body: { objectType, relation, subjectType, subjectId, cursor?, limit? }.
SDK Usage
React
import { useFga } from '@auris/react'
function DocumentPage({ documentId }) {
const { check, listObjects, isLoading } = useFga()
const [canEdit, setCanEdit] = useState(false)
useEffect(() => {
check({
object: `document:${documentId}`,
relation: 'editor',
}).then((result) => setCanEdit(result.allowed))
}, [documentId])
return (
<div>
<h1>Document</h1>
{canEdit ? (
<button>Edit Document</button>
) : (
<span>Read-only</span>
)}
</div>
)
}
// Sharing panel — show who has access
function SharingPanel({ documentId }) {
const { expand } = useFga()
const [viewers, setViewers] = useState([])
useEffect(() => {
expand({
objectType: 'document',
objectId: documentId,
relation: 'viewer',
}).then((result) => setViewers(result.subjects))
}, [documentId])
return (
<ul>
{viewers.map((viewer) => (
<li key={viewer.subjectId}>{viewer.subjectId}</li>
))}
</ul>
)
}Common Patterns
Google Drive Model
A hierarchy where folder permissions propagate to documents:
type user
type folder
relations
define owner: [user]
define editor: [user] or owner
define viewer: [user] or editor
define parent: [folder]
define editor_via_parent: editor from parent
define viewer_via_parent: viewer from parent
type document
relations
define owner: [user]
define parent_folder: [folder]
define editor: [user] or owner or editor_via_parent from parent_folder
define viewer: [user] or editor or viewer_via_parent from parent_folderSaaS Multi-Tenant Model
Organization membership controls access to projects and resources:
type user
type organization
relations
define admin: [user]
define member: [user] or admin
type project
relations
define organization: [organization]
define admin: [user] or admin from organization
define member: [user] or member from organization or admin
type resource
relations
define project: [project]
define owner: [user]
define editor: [user] or owner or admin from project
define viewer: [user] or editor or member from projectDebugging with the FGA Console
The Auris Console includes a FGA Debugger at Console → Authorization → Debugger with three tools:
- Check: Test any object/relation/subject combination and see the resolution tree
- Expand: Visualize the full subject set for any relation
- List Objects: Find all objects a user has access to
The resolution tree shows exactly which tuples and model rewrites led to the allowed: true or allowed: false result — essential for diagnosing unexpected authorization outcomes.
Model Templates
The Console provides three model templates to get started quickly:
- Basic: Simple user/resource model with owner, editor, viewer
- SaaS: Organization → project → resource hierarchy with team membership
- Drive: Nested folder/document hierarchy with inherited permissions
Related Guides
- Roles & Permissions (RBAC) — Role-based authorization for application-level permissions
- Custom JWT Claims — Embed FGA-derived data in access tokens
- M2M Client Credentials — Server-side FGA checks from backend services