Authdog

FGA

Last updated Nov 9, 2026
View as Markdown

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 parent

This 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: owner

Tuples:

# 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