Skip to content

Commit f53ad4b

Browse files
authored
Merge pull request #52 from aaguiarz/feat/fga-for-mcp
Add FGA for MCP Example
2 parents f44c3de + 3f252a8 commit f53ad4b

File tree

19 files changed

+3985
-1
lines changed

19 files changed

+3985
-1
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
AUTH0_DOMAIN=
2+
AUTH0_AUDIENCE=
3+
PORT=3001
4+
MCP_SERVER_URL=http://localhost:3001
5+
6+
# Get these from dashboard.fga.dev / Store Settings
7+
FGA_API_URL='https://api.us1.fga.dev'
8+
FGA_STORE_ID=<store_id>
9+
FGA_API_TOKEN_ISSUER='auth.fga.dev'
10+
FGA_API_AUDIENCE='https://api.us1.fga.dev/'
11+
FGA_CLIENT_ID='<client_id>'
12+
FGA_CLIENT_SECRET='<client_secret>'
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
# Example FastMCP MCP Server with Auth0 and Auth0 FGA Integration
2+
3+
This is a practical example of securing a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/docs) server
4+
with Auth0 using the [FastMCP](https://github.com/punkpeye/fastmcp) TypeScript framework.
5+
6+
This repository shows a minimal but realistic integration with:
7+
- OAuth 2.0 / OIDC via Auth0 for authentication and token verification
8+
- Auth0 FGA (OpenFGA) for fine-grained Resource Authorization
9+
- FastMCP for exposing tools as MCP endpoints
10+
11+
This example uses an authorization model defined in [`fga/model.fga`](./fga/model.fga) that supports:
12+
13+
- **Public Tools**: Accessible to all authenticated users (e.g., `get_datetime`)
14+
- **Role-Based Access**: Tools assigned to specific roles
15+
- **Group Membership**: Users inherit permissions through group membership
16+
- **Temporal Access**: Time-limited tool access with automatic expiration
17+
- **Resource-Specific Permissions**: Fine-grained access (e.g., viewing private documents)
18+
19+
## Prerequisites
20+
21+
- Node.js 18+
22+
- npm (or a compatible package manager)
23+
- An Auth0 tenant (for OAuth and token verification)
24+
- An Auth0 FGA account (OpenFGA / fga.dev) for authorization model and tuples
25+
- `fga` CLI (optional, for bootstrapping the model and tuples)
26+
27+
## Available Tools
28+
29+
The server exposes the following tools:
30+
31+
- `whoami` - Returns authenticated user information and granted scopes
32+
- `greet` - Personalized greeting demonstrating authenticated tool access
33+
- `get_datetime` Returns the current UTC date and time (no scope required)
34+
- `get_documents` - Returns a list of documents from a mock API. Depending on the user role, it will return private documents or not.
35+
36+
## Install dependencies
37+
38+
Install the dependencies using npm:
39+
40+
```bash
41+
npm install
42+
```
43+
44+
## Auth0 Tenant Setup
45+
46+
For detailed instructions on setting up your Auth0 tenant for MCP server integration, please refer to the [Auth0 Tenant Setup guide](https://github.com/auth0-samples/auth0-ai-samples/tree/main/auth-for-mcp/fastmcp-mcp-js/README.md#auth0-tenant-setup) in the FastMCP example.
47+
48+
## Auth0 FGA Setup
49+
50+
Auth0 FGA provides fine-grained authorization using [Relationship-Based Access Control (ReBAC)](https://docs.fga.dev/concepts#what-is-relationship-based-access-control-rebac). It's built on [OpenFGA](https://openfga.dev), a CNCF incubation project, and offers more flexible authorization patterns than traditional RBAC.
51+
52+
### Prerequisites
53+
54+
1. **Create an Auth0 FGA Account**: Sign up for free at [fga.dev](https://fga.dev)
55+
2. **Generate API Credentials**: Follow [this guide](https://docs.fga.dev/intro/settings) to create credentials with full permissions
56+
3. **Install the FGA CLI**:
57+
```bash
58+
# macOS
59+
brew install openfga/tap/fga
60+
61+
# Other platforms - download from:
62+
# https://github.com/openfga/cli/releases
63+
```
64+
65+
### CLI Configuration
66+
67+
After creating your FGA credentials, export the following (provided during credential creation):
68+
69+
```bash
70+
export FGA_API_URL='https://api.us1.fga.dev'
71+
export FGA_STORE_ID='<your-store-id>'
72+
export FGA_API_TOKEN_ISSUER='auth.fga.dev'
73+
export FGA_API_AUDIENCE='https://api.us1.fga.dev/'
74+
export FGA_CLIENT_ID='<your-client-id>'
75+
export FGA_CLIENT_SECRET='<your-client-secret>'
76+
```
77+
78+
### Authorization Model
79+
80+
81+
### Initial Setup
82+
83+
1. **Deploy the Authorization Model**:
84+
```bash
85+
fga model write --file ./fga/model.fga
86+
```
87+
88+
2. **Import Initial Data**: The [`fga/tuples.yaml`](./fga/tuples.yaml) file defines:
89+
- Two roles: `admin` and `content_manager`
90+
- Two groups: `marketing` (content_manager role) and `managers` (admin role)
91+
- Tool permissions:
92+
- Everyone: `get_datetime`
93+
- Admin & Content Manager: `greet`, `whoami`, `get_documents`
94+
- Admin only: Can view private documents
95+
96+
Import the tuples:
97+
```bash
98+
fga tuple write --file ./fga/tuples.yaml
99+
```
100+
101+
### Managing User Access
102+
103+
Use the provided scripts to manage user permissions dynamically:
104+
105+
#### Add User to Group
106+
Grants all permissions associated with the group:
107+
108+
```bash
109+
# Add user to managers group (admin role - full access including private documents)
110+
./fga/add-user-to-group.sh user@example.com managers
111+
112+
# Add user to marketing group (content_manager role - no private document access)
113+
./fga/add-user-to-group.sh user@example.com marketing
114+
```
115+
116+
#### Remove User from Group
117+
Revokes group-based permissions:
118+
119+
```bash
120+
./fga/remove-user-from-group.sh user@example.com managers
121+
```
122+
123+
#### Grant Temporary Access
124+
Provides time-limited access to specific tools:
125+
126+
```bash
127+
# Grant 20-second access to the greet tool
128+
./fga/add-temporal-access.sh user@example.com greet 20s
129+
130+
# Grant 1-hour access
131+
./fga/add-temporal-access.sh user@example.com greet 1h
132+
```
133+
134+
Temporal access automatically expires.
135+
136+
### Testing Access Changes
137+
138+
After modifying permissions, test with different users to verify:
139+
140+
1. **Managers Group** (admin role):
141+
- Should see: `get_datetime`, `greet`, `whoami`, `get_documents`
142+
- Can view: All documents (public + private)
143+
144+
2. **Marketing Group** (content_manager role):
145+
- Should see: `get_datetime`, `greet`, `whoami`, `get_documents`
146+
- Can view: Public documents only
147+
148+
3. **User with Temporal Access**:
149+
- Should see: `get_datetime` + temporarily granted tool
150+
- Access expires after specified duration
151+
152+
4. **User with No Assignments**:
153+
- Should see: `get_datetime` only
154+
155+
You can also manage tuples directly in the [Auth0 FGA Dashboard](https://dashboard.fga.dev) for.
156+
157+
## Configuration
158+
159+
Rename `.env.example` to `.env` and configure the domain and audience:
160+
161+
```
162+
# Auth0 tenant domain
163+
AUTH0_DOMAIN=example-tenant.us.auth0.com
164+
165+
# Auth0 API Identifier
166+
AUTH0_AUDIENCE=http://localhost:3001/
167+
168+
# FGA Configuration
169+
FGA_API_URL='https://api.us1.fga.dev'
170+
FGA_STORE_ID=<store_id>
171+
FGA_API_TOKEN_ISSUER='auth.fga.dev'
172+
FGA_API_AUDIENCE='https://api.us1.fga.dev/'
173+
FGA_CLIENT_ID='<client_secret>'
174+
FGA_CLIENT_SECRET='<client_secret>'
175+
```
176+
177+
With the configuration in place, the example can be started by running:
178+
179+
```bash
180+
npm run start
181+
```
182+
183+
## Testing
184+
185+
Use an MCP client like [MCP Inspector](https://github.com/modelcontextprotocol/inspector) to test your server interactively:
186+
187+
```bash
188+
npx @modelcontextprotocol/inspector
189+
```
190+
191+
The server will start up and the UI will be accessible at http://localhost:6274.
192+
193+
In the MCP Inspector, select `Streamable HTTP` as the `Transport Type`, enter `http://localhost:3001/mcp` as the URL, and select `Via Proxy` for `Connection Type`.
194+
195+
### Using cURL
196+
197+
You can use cURL to verify that the server is running:
198+
199+
```bash
200+
# Test that the server is running and accessible - check OAuth resource metadata
201+
curl -v http://localhost:3001/.well-known/oauth-protected-resource
202+
203+
# Test MCP initialization (requires valid Auth0 access token)
204+
curl -X POST http://localhost:3001/mcp \
205+
-H "Content-Type: application/json" \
206+
-H "Accept: application/json, text/event-stream" \
207+
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
208+
-d '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "curl-test", "version": "1.0.0"}}}'
209+
210+
# Test get_datetime tool (no scope required) - outputs ISO string like 2025-10-31T14:12:03.123Z
211+
curl -X POST http://localhost:3001/mcp \
212+
-H "Content-Type: application/json" \
213+
-H "Accept: application/json, text/event-stream" \
214+
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
215+
-d '{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "get_datetime", "arguments": {}}}'
216+
```

0 commit comments

Comments
 (0)