Agentic AuthZ Demo

May 12, 2026 · View on GitHub

Fine-grained authorization for AI agents using OpenFGA.

AI agents are getting access to production systems - databases, APIs, file systems. But who decides what they can do? Traditional RBAC wasn't designed for autonomous agents that make decisions without human approval.

This demo shows how to implement Relationship-Based Access Control (ReBAC) for AI agents using OpenFGA, with three levels of authorization:

  1. Team Level - Which teams can use which tool categories
  2. Project Level - Which projects have access to which resources
  3. Operation Level - Fine-grained control over destructive operations

Quick Start

# Start services and seed data
make setup

# Run the demo
make demo

# Or use the interactive script
./scripts/demo.sh

Why This Matters

ProblemSolution
Agent has same permissions as userFine-grained, context-aware permissions
Prompt injection → data exfiltrationBlast radius contained by project scope
No audit trail for agent actionsEvery authorization decision logged
"All or nothing" tool accessOperation-level restrictions

Architecture

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   AI Agent      │────▶│   Gateway       │────▶│   OpenFGA       │
│   (Claude/GPT)  │     │   (Go)          │     │   (AuthZ)       │
└─────────────────┘     └─────────────────┘     └─────────────────┘


                        ┌─────────────────┐
                        │   MCP Tools     │
                        │   (Mock/Real)   │
                        └─────────────────┘

Authorization Model

Three levels of access control:

1. Team Level

Teams are assigned to tool categories.

TeamCode ToolsCommunicationData ToolsInfrastructure
Engineering
Marketing
DevOps

2. Project Level

Projects have specific tool access.

ProjectGitHubSlackPostgresFilesystem
auth-service
landing-page
infrastructure

3. Operation Level

Specific operations are restricted to certain roles.

OperationAllowed Roles
github:delete_repoTeam Leads only
postgres:deleteTeam Leads only

Demo Scenarios

#ScenarioUserToolExpected
1Engineering → GitHubAlice (lead)github:create_pr✅ Allowed
2Marketing → GitHubBob (lead)github:create_pr❌ Denied
3auth-service → PostgresAlicepostgres:query✅ Allowed
4landing-page → PostgresBobpostgres:query❌ Denied
5Member → delete_repoCharliegithub:delete_repo❌ Denied
6Lead → delete_repoAlicegithub:delete_repo✅ Allowed

Services

ServicePortDescription
Demo UI3002Interactive demo interface
Admin UI3001Permission management dashboard
OpenFGA Playground3000OpenFGA visual explorer
Gateway API9000Authorization gateway
OpenFGA API8080OpenFGA HTTP API

Development

# Install dependencies
make install-deps

# Start OpenFGA
make setup-openfga

# Run gateway in mock mode
make dev-gateway

# Run Demo UI
make dev-demo

# Run Admin UI
make dev-admin

API Endpoints

Check Authorization

curl -X POST http://localhost:9000/v1/tools/call \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "github",
    "operation": "create_pr",
    "params": {"title": "My PR"},
    "context": {
      "user": "alice",
      "project": "auth-service",
      "team": "engineering"
    }
  }'

List Tools

curl http://localhost:9000/v1/tools

View Audit Log

curl http://localhost:9000/v1/audit

List Demo Scenarios

curl http://localhost:9000/v1/demo/scenarios

Project Structure

agentic-authz/
├── gateway/              # Go authorization gateway
│   ├── cmd/gateway/      # Main entry point
│   └── internal/         # Internal packages
│       ├── authz/        # OpenFGA client
│       ├── config/       # Configuration
│       ├── handler/      # HTTP handlers
│       └── mcp/          # MCP proxy
├── demo-ui/              # Next.js demo interface
├── admin-ui/             # Next.js admin dashboard
├── openfga/              # Authorization model
│   ├── model.fga         # FGA DSL model
│   ├── model.json        # JSON model for API
│   └── tuples.json       # Seed data
├── scripts/              # Demo scripts
├── docker-compose.yml    # Service orchestration
└── Makefile              # Build commands

OpenFGA Model

The authorization model uses OpenFGA's DSL:

type tool
  relations
    define category: [tool_category]
    define allowed_team: [team]
    define can_use: member from allowed_team or can_use from category

type tool_operation
  relations
    define tool: [tool]
    define allowed_role: [user]
    define can_execute: allowed_role or can_use from tool

Make Commands

make help           # Show all commands
make setup          # Full setup
make demo           # Run all demo scenarios
make audit          # View audit log
make tools          # List available tools
make users          # List demo users
make projects       # List demo projects
make clean          # Stop and clean up

The Security Case for Agent Authorization

The Problem

User: "Summarize our Q4 sales data"
Agent: *has database access*
Agent: SELECT * FROM users; DROP TABLE users;--

Without fine-grained authorization, a compromised or manipulated agent can:

  • Access data outside its task scope
  • Perform destructive operations
  • Pivot between systems
  • Exfiltrate sensitive information

The Solution

User: "Summarize our Q4 sales data"
Agent: *requests database access*
Gateway: Check(user:alice, can_execute, tool_operation:postgres:query)
OpenFGA: ✅ ALLOWED (project:sales-dashboard has postgres access)
Agent: SELECT SUM(revenue) FROM sales WHERE quarter='Q4'

With this architecture:

  • Every tool call is authorized
  • Permissions are scoped to project context
  • Destructive operations require elevated privileges
  • All decisions are audited

Real-World Use Case: Confidential AI Platforms

When AI coding agents work on security-critical codebases, the blast radius of a compromised or misdirected agent is much larger than in a typical project. This pattern applies directly to confidential computing stacks where certain components must never be touched by an agent.

Example: Confidential AI inference platform (Intel TDX)

A typical confidential AI stack has components where agent write access would be catastrophic:

ComponentWhy it matters
cvm/attestation-service/TDX quote generation and EKM validation logic
cvm/auth-service/Bearer token auth and HMAC comparison
cvm/cert-manager/TLS cert and EKM shared secret

A developer running a frontend review agent should have no access to these components. With agentic-authz, this is expressed as the absence of tuples — no tuple written means no access, full stop.

# Grant the frontend review agent access to the frontend only
fga tuple write \
  '{"object":"repo:my-project/frontend","relation":"reader","user":"agent:frontend-review-agent"}'

# No tuples written for attestation-service, auth-service, cert-manager.
# The agent cannot read or write those components regardless of what it "decides."

# Verify
fga query check --user agent:frontend-review-agent \
  --relation reader --object repo:my-project/attestation-service
# { "allowed": false }

Connecting attestation identity to authorization

For platforms using attested TLS, the TEE's measurement (e.g. app_compose_hash from a TDX attestation report) can serve as the identity anchor in OpenFGA tuples:

# After verifying the TEE attestation, extract the identity
tee_identity = report.tdx.app_compose_hash  # deterministic per deployment

allowed = await fga.check(
    user=f"tee:{tee_identity}",
    relation="can_invoke",
    object="service:inference-endpoint"
)

This gives confidential AI platforms a full authorization layer on top of their existing attestation stack: the aTLS layer handles authentication (who is connecting), OpenFGA handles authorization (what they can do).


Resources

Author

Built by Siddhant Khare - OpenFGA Core Maintainer

Helping teams implement secure AI agent architectures.

License

MIT