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:
- Team Level - Which teams can use which tool categories
- Project Level - Which projects have access to which resources
- Operation Level - Fine-grained control over destructive operations
# Start services and seed data
make setup
# Run the demo
make demo
# Or use the interactive script
./scripts/demo.sh| Problem | Solution |
|---|---|
| Agent has same permissions as user | Fine-grained, context-aware permissions |
| Prompt injection → data exfiltration | Blast radius contained by project scope |
| No audit trail for agent actions | Every authorization decision logged |
| "All or nothing" tool access | Operation-level restrictions |
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ AI Agent │────▶│ Gateway │────▶│ OpenFGA │
│ (Claude/GPT) │ │ (Go) │ │ (AuthZ) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ MCP Tools │
│ (Mock/Real) │
└─────────────────┘
Three levels of access control:
Teams are assigned to tool categories.
| Team | Code Tools | Communication | Data Tools | Infrastructure |
|---|---|---|---|---|
| Engineering | ✅ | ✅ | ✅ | ❌ |
| Marketing | ❌ | ✅ | ❌ | ❌ |
| DevOps | ✅ | ✅ | ✅ | ✅ |
Projects have specific tool access.
| Project | GitHub | Slack | Postgres | Filesystem |
|---|---|---|---|---|
| auth-service | ✅ | ✅ | ✅ | ❌ |
| landing-page | ❌ | ✅ | ❌ | ❌ |
| infrastructure | ✅ | ✅ | ✅ | ✅ |
Specific operations are restricted to certain roles.
| Operation | Allowed Roles |
|---|---|
github:delete_repo |
Team Leads only |
postgres:delete |
Team Leads only |
| # | Scenario | User | Tool | Expected |
|---|---|---|---|---|
| 1 | Engineering → GitHub | Alice (lead) | github:create_pr |
✅ Allowed |
| 2 | Marketing → GitHub | Bob (lead) | github:create_pr |
❌ Denied |
| 3 | auth-service → Postgres | Alice | postgres:query |
✅ Allowed |
| 4 | landing-page → Postgres | Bob | postgres:query |
❌ Denied |
| 5 | Member → delete_repo | Charlie | github:delete_repo |
❌ Denied |
| 6 | Lead → delete_repo | Alice | github:delete_repo |
✅ Allowed |
| Service | Port | Description |
|---|---|---|
| Demo UI | 3002 | Interactive demo interface |
| Admin UI | 3001 | Permission management dashboard |
| OpenFGA Playground | 3000 | OpenFGA visual explorer |
| Gateway API | 9000 | Authorization gateway |
| OpenFGA API | 8080 | OpenFGA HTTP API |
# 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-admincurl -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"
}
}'curl http://localhost:9000/v1/toolscurl http://localhost:9000/v1/auditcurl http://localhost:9000/v1/demo/scenariosagentic-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
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 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 upUser: "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
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
Built by Siddhant Khare - OpenFGA Core Maintainer
- X: @siddhant_K_code
- GitHub: @Siddhant-K-code
- LinkedIn: Siddhant Khare
Helping teams implement secure AI agent architectures.
MIT