OpenFGA provides Google Zanzibar-style relationship-based authorization for fine-grained access control. This guide covers deployment, configuration, and integration with your MCP Server.
OpenFGA is the same authorization model used by Google, Airbnb, GitHub, and other companies handling billions of permission checks per day.
# Check OpenFGA healthcurl http://localhost:8080/healthz# Expected response{"status":"SERVING"}# Check versioncurl http://localhost:8080/# Expected: OpenFGA version info
3
Run Setup Script
Copy
Ask AI
# Initialize store and modelpython scripts/setup/setup_openfga.py
Output:
Copy
Ask AI
============================================================OpenFGA Setup============================================================1. Connecting to OpenFGA at http://localhost:8080...2. Creating authorization store and model... ✓ Store created: 01HXXXXXXXXXXXXXXXXXX ✓ Model created: 01HYYYYYYYYYYYYYYYYYY3. Update your .env file with: OPENFGA_STORE_ID=01HXXXXXXXXXXXXXXXXXX OPENFGA_MODEL_ID=01HYYYYYYYYYYYYYYYYYY4. Seeding sample relationship data... ✓ Sample data seeded5. Verifying authorization checks... ✓ Test 1: user:alice can executor tool:chat: True ✓ Test 2: user:bob can executor tool:chat: True ✓ Test 3: user:alice can owner conversation:thread_1: True ✓ Test 4: user:bob can owner conversation:thread_1: False ✓ Test 5: user:bob can viewer conversation:thread_1: True============================================================✓ OpenFGA setup completed successfully!============================================================
## What can user access?tools = await client.list_objects( user="user:alice", relation="executor", object_type="tool")print(f"Alice can execute: {tools}")## Output: ['tool:chat', 'tool:search']## Who can access this object?users = await client.list_users( relation="executor", object="tool:chat")print(f"Can execute chat: {users}")## Output: ['user:alice', 'user:bob']
## Revoke specific permissionawait client.delete_tuples([{ "user": "user:bob", "relation": "executor", "object": "tool:chat"}])## Revoke all user permissions for an objecttuples = await client.read_tuples(object="tool:chat")user_tuples = [t for t in tuples if t['user'] == 'user:bob']await client.delete_tuples(user_tuples)
Always use PostgreSQL in production (not in-memory):
Copy
Ask AI
## Connection stringOPENFGA_DATASTORE_URI=postgres://openfga:password@postgres:5432/openfga?sslmode=require## With connection poolingOPENFGA_DATASTORE_MAX_OPEN_CONNS=25OPENFGA_DATASTORE_MAX_IDLE_CONNS=10OPENFGA_DATASTORE_CONN_MAX_IDLE_TIME=60s
PostgreSQL Configuration:
Copy
Ask AI
-- Create databaseCREATE DATABASE openfga;-- Create userCREATE USER openfga WITH PASSWORD 'strong-password';GRANT ALL PRIVILEGES ON DATABASE openfga TO openfga;-- Enable extensionsCREATE EXTENSION IF NOT EXISTS "uuid-ossp";CREATE EXTENSION IF NOT EXISTS "pg_trgm";
all_tuples = await client.read_tuples()
matching = [t for t in all_tuples
if t[‘user’] == ‘user:alice’
and t[‘object’] == ‘tool:chat’]
print(f”Matching tuples: “)