Skip to content

Authorization

ToolMesh uses OpenFGA for fine-grained authorization. The model follows a User → Plan → Tool relationship structure.

ModeConfigBehavior
bypassOPENFGA_MODE=bypassNo authorization checks (default)
restrictOPENFGA_MODE=restrictOpenFGA enforced on every tool call

Start with bypass for development, switch to restrict for production.

User --member_of--> Plan --can_execute--> Tool

Each user (from OAuth login or API key) has an assigned plan. Plans grant access to specific tools. When a tool call arrives, ToolMesh checks:

Check(user, can_execute, tool)

If denied, the execution stops immediately with an unauthorized error.

DADL tools declare an access classification:

LevelMeaning
readRead-only operations
writeCreate/update operations
adminAdministrative operations
dangerousDestructive or irreversible operations
customExtendable with any string value

Policy files bundle these access levels into roles, and OpenFGA assigns roles to users.

Terminal window
OPENFGA_API_URL=http://openfga:8080 # OpenFGA API endpoint (Docker service name)
OPENFGA_STORE_ID=your-store-id # OpenFGA store ID
OPENFGA_MODE=restrict # Enable enforcement

The authorization model and relationship tuples are defined as editable files in config/openfga/:

FilePurpose
model.fgaAuthorization model in FGA DSL
tuples.jsonUser/plan/tool relationships
setup.shShell script that uses the fga CLI to apply model and tuples

The setup.sh script runs on the host and uses docker run with the openfga/cli image to apply the model and tuples (the CLI image is distroless and has no shell, so it cannot run as a Docker Compose service):

Terminal window
# 1. Uncomment the OpenFGA services in docker-compose.yml (+ mysqldata volume)
# 2. Start all services
docker compose up -d
# 3. Bootstrap the OpenFGA store
./config/openfga/setup.sh
# 4. Copy the OPENFGA_STORE_ID from the output into .env
# 5. Set OPENFGA_MODE=restrict in .env
# 6. Restart
docker compose down && docker compose up -d

The default tuples.json demonstrates authorization with a deny case:

  • Free plan (all users via wildcard): can execute echo_echo and echo_time, but not echo_add
  • Pro plan (company:acme members): can execute all tools

This lets you verify that authorization works correctly out of the box — free-plan users are denied access to echo_add.

Authorization decisions can also consider the CallerClass (trusted, standard, untrusted). This allows policies like “untrusted clients cannot access admin tools” even if the user’s plan would normally allow it.