Fine-grained authorization (FGA) models access as relationships between users and objects. This quickstart walks through setting up FGA with relationship tuples.
Prerequisites
- An Authdog account with at least one tenant and environment
- An environment API secret (
adenv_...)
When to use FGA
FGA is the right choice when:
- Access is defined per object, not per role ("Anne can edit document X")
- Permissions inherit through a hierarchy (folder → documents inside)
- You need to answer "which objects can this user access?" efficiently
- Sharing and collaboration are core to your product
1. Enable FGA for the environment
Console: Authorization → Model → select FGA
This opens the FGA module with Getting Started, Model Explorer, and Tuple Management.
2. Define your authorization model
The model describes your object types, their relations, and how relations inherit.
Console: FGA → Model Explorer
Example model:
model
schema 1.1
type user
type group
relations
define member: [user]
type folder
relations
define owner: [user]
define viewer: [user, user:*, group#member] or owner
type document
relations
define parent: [folder]
define owner: [user]
define editor: [user, group#member] or owner
define viewer: [user, user:*, group#member] or editor or viewer from parentThis model says:
- A folder has owners and viewers
- A document has a parent folder, plus its own owners, editors, and viewers
- Document viewers include anyone who can view the parent folder
API:
curl -X POST https://api.authdog.com/fga/v1/models \
-H "Authorization: Bearer $AUTHDOG_ENV_API_SECRET" \
-H "Content-Type: application/json" \
-d '{"model": "model\n schema 1.1\n\ntype user\n\ntype folder\n relations\n define owner: [user]\n define viewer: [user] or owner\n\ntype document\n relations\n define parent: [folder]\n define owner: [user]\n define editor: [user] or owner\n define viewer: [user] or editor or viewer from parent"}'3. Write relationship tuples
Tuples are facts: "user:anne is editor of document:roadmap".
Console: FGA → Tuple Management → Add Tuple
API:
# Anne is owner of the engineering folder
curl -X POST https://api.authdog.com/fga/v1/write \
-H "Authorization: Bearer $AUTHDOG_ENV_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"writes": [
{"object": "folder:eng", "relation": "owner", "subject": "user:anne"}
]
}'
# The roadmap doc is inside the engineering folder
curl -X POST https://api.authdog.com/fga/v1/write \
-H "Authorization: Bearer $AUTHDOG_ENV_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"writes": [
{"object": "document:roadmap", "relation": "parent", "subject": "folder:eng"}
]
}'
# Bob is editor of the roadmap doc
curl -X POST https://api.authdog.com/fga/v1/write \
-H "Authorization: Bearer $AUTHDOG_ENV_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"writes": [
{"object": "document:roadmap", "relation": "editor", "subject": "user:bob"}
]
}'4. Check permissions
Ask: "Can user:anne view document:roadmap?"
API:
curl -X POST https://api.authdog.com/fga/v1/check \
-H "Authorization: Bearer $AUTHDOG_ENV_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"object": "document:roadmap",
"relation": "viewer",
"subject": "user:anne"
}'
# → {"allowed": true}Anne can view because she owns folder:eng, and document:roadmap inherits viewer from its parent folder.
With trace (shows the proof path):
curl -X POST https://api.authdog.com/fga/v1/check \
-H "Authorization: Bearer $AUTHDOG_ENV_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"object": "document:roadmap",
"relation": "viewer",
"subject": "user:anne",
"trace": true
}'
# → {"allowed": true, "trace": {"kind": "relation", "label": "document:roadmap#viewer", "children": [...]}}5. List objects a user can access
For a list page, you need all objects a user can reach, not one check per object.
curl -X POST https://api.authdog.com/fga/v1/list-objects \
-H "Authorization: Bearer $AUTHDOG_ENV_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"type": "document",
"relation": "viewer",
"subject": "user:anne"
}'
# → {"objects": ["document:roadmap", "document:spec", ...]}6. Use in your app
SDK (Node.js):
import { Authdog } from "@authdog/node"
const authdog = new Authdog({ envApiSecret: process.env.AUTHDOG_ENV_API_SECRET })
app.get("/documents/:id", requireAuth, async (req, res) => {
const allowed = await authdog.fga.check({
object: `document:${req.params.id}`,
relation: "viewer",
subject: `user:${req.user.id}`,
})
if (!allowed) {
return res.status(403).json({ error: "Forbidden" })
}
const doc = await getDocument(req.params.id)
res.json(doc)
})
app.get("/documents", requireAuth, async (req, res) => {
const { objects } = await authdog.fga.listObjects({
type: "document",
relation: "viewer",
subject: `user:${req.user.id}`,
})
const docs = await getDocumentsByIds(objects.map(o => o.split(":")[1]))
res.json(docs)
})7. Write assertions for testing
Assertions are saved checks that must pass. Use them to verify your model before production.
Console: FGA → Developer Mode → add assertions → Run All
API:
curl -X PUT https://api.authdog.com/fga/v1/assertions/latest \
-H "Authorization: Bearer $AUTHDOG_ENV_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"assertions": [
{"object": "document:roadmap", "relation": "viewer", "subject": "user:anne", "expected": true},
{"object": "document:roadmap", "relation": "editor", "subject": "user:anne", "expected": false},
{"object": "document:roadmap", "relation": "editor", "subject": "user:bob", "expected": true}
]
}'Example: Google Drive-style sharing
model
schema 1.1
type user
type group
relations
define member: [user]
type folder
relations
define owner: [user]
define editor: [user, group#member] or owner
define viewer: [user, user:*, group#member] or editor
type file
relations
define parent: [folder]
define owner: [user]
define editor: [user, group#member] or owner or editor from parent
define viewer: [user, user:*, group#member] or editor or viewer from parent
define can_share: ownerTuples:
# Engineering team can view the eng folder
{"object": "folder:eng", "relation": "viewer", "subject": "group:engineering#member"}
# Alice owns her personal folder
{"object": "folder:alice-personal", "relation": "owner", "subject": "user:alice"}
# Design doc is in the eng folder
{"object": "file:design-doc", "relation": "parent", "subject": "folder:eng"}
# Bob can edit the design doc directly
{"object": "file:design-doc", "relation": "editor", "subject": "user:bob"}CLI usage
CLI support for FGA commands is coming soon. For now, use the generic API command:
# Check permission
authdog api POST /fga/v1/check --data '{"object":"document:roadmap","relation":"viewer","subject":"user:anne"}'
# Write tuple
authdog api POST /fga/v1/write --data '{"writes":[{"object":"document:spec","relation":"editor","subject":"user:carol"}]}'
# List objects
authdog api POST /fga/v1/list-objects --data '{"type":"document","relation":"viewer","subject":"user:anne"}'Next steps
- FGA reference — full API documentation
- FGA console module — model explorer, tuples, assertions, logs
- Authorization concepts — compare FGA with RBAC and ABAC