Skip to content

Commit f001fe3

Browse files
committed
oauth working for basic in-memory provider
Signed-off-by: phernandez <paul@basicmachines.co>
1 parent a35fc37 commit f001fe3

7 files changed

Lines changed: 390 additions & 496 deletions

File tree

AUTH.md

Lines changed: 28 additions & 300 deletions
Original file line numberDiff line numberDiff line change
@@ -1,314 +1,42 @@
1-
# OAuth Quick Start Guide
1+
# OAuth Quick Start
22

3-
This guide shows how to test OAuth authentication with Basic Memory MCP server, including how to connect from Claude.ai.
3+
Basic Memory supports OAuth authentication for secure access control. For detailed documentation, see [OAuth Authentication Guide](docs/OAuth%20Authentication%20Guide.md).
44

5-
## MCP Inspector Testing
5+
## Quick Test with MCP Inspector
66

7-
To test with MCP Inspector when OAuth is enabled:
7+
```bash
8+
# 1. Set a consistent secret key
9+
export FASTMCP_AUTH_SECRET_KEY="test-secret-key"
810

9-
1. **Start the server with OAuth**:
10-
```bash
11-
FASTMCP_AUTH_ENABLED=true basic-memory mcp --transport streamable-http
12-
```
11+
# 2. Start server with OAuth
12+
FASTMCP_AUTH_ENABLED=true basic-memory mcp --transport streamable-http
1313

14-
2. **Register a client** (in another terminal):
15-
```bash
16-
basic-memory auth register-client --client-id=test-client
17-
# Save the client_secret that's generated!
18-
```
14+
# 3. In another terminal, get a test token
15+
export FASTMCP_AUTH_SECRET_KEY="test-secret-key" # Same key!
16+
basic-memory auth test-auth
1917

20-
3. **Get an access token**:
21-
```bash
22-
# Test the flow to get a token
23-
basic-memory auth test-auth
24-
# Look for "Access token: ..." in the output
25-
```
26-
27-
4. **Use token in MCP Inspector**:
28-
- Header Name: `Authorization`
29-
- Bearer Token: `<paste the access token from step 3>`
30-
31-
Or manually get a token:
32-
```bash
33-
# Get authorization code
34-
curl "http://localhost:8000/auth/authorize?client_id=test-client&redirect_uri=http://localhost:3000/callback&response_type=code&code_challenge=test"
35-
36-
# Exchange for token (use code from redirect URL)
37-
curl -X POST http://localhost:8000/auth/token \
38-
-H "Content-Type: application/x-www-form-urlencoded" \
39-
-d "grant_type=authorization_code&code=YOUR_CODE&client_id=test-client&client_secret=YOUR_SECRET&code_verifier=test"
40-
```
41-
42-
## Local Testing with Built-in Provider
43-
44-
1. **Create `.env` file**:
45-
```bash
46-
cp .env.oauth.example .env
47-
```
48-
49-
2. **Enable OAuth** in `.env`:
50-
```bash
51-
FASTMCP_AUTH_ENABLED=true
52-
FASTMCP_AUTH_PROVIDER=basic
53-
```
54-
55-
3. **Start the server**:
56-
```bash
57-
# Using environment variables
58-
basic-memory mcp --transport streamable-http
59-
60-
# Or directly
61-
62-
```
63-
64-
4. **Register a client**:
65-
```bash
66-
basic-memory auth register-client
67-
# Save the client_id and client_secret!
68-
```
69-
70-
5. **Test the flow**:
71-
```bash
72-
basic-memory auth test-auth
73-
```
74-
75-
## Production with Supabase
76-
77-
1. **Create Supabase project** at [supabase.com](https://supabase.com)
78-
79-
2. **Configure `.env`**:
80-
```bash
81-
FASTMCP_AUTH_ENABLED=true
82-
FASTMCP_AUTH_PROVIDER=supabase
83-
SUPABASE_URL=https://your-project.supabase.co
84-
SUPABASE_ANON_KEY=your-anon-key
85-
SUPABASE_SERVICE_KEY=your-service-key
86-
```
87-
88-
3. **Start the server**:
89-
```bash
90-
basic-memory mcp --transport streamable-http
91-
```
92-
93-
## OAuth Endpoints
94-
95-
When OAuth is enabled, these endpoints are available:
96-
97-
- `GET /auth/authorize` - OAuth authorization endpoint
98-
- `POST /auth/token` - Token exchange endpoint
99-
- `GET /mcp` - Protected MCP endpoint (requires Bearer token)
100-
101-
## Testing with MCP Inspector
102-
103-
**Note**: The OAuth2 flow typically requires browser interaction. With MCP Inspector, you can use bearer token authentication directly.
104-
105-
### Bearer Token Approach
106-
107-
1. Run the test-auth command to get tokens:
108-
```bash
109-
basic-memory auth test-auth
110-
```
111-
This will output an access token that you can copy.
112-
113-
2. In MCP Inspector:
114-
- Server URL: `http://localhost:8000/mcp`
115-
- Transport: `streamable-http`
116-
- Add custom headers:
117-
```
118-
Authorization: Bearer YOUR_ACCESS_TOKEN
119-
```
120-
121-
### Full OAuth Flow Testing
122-
123-
If you want to test the full OAuth flow:
124-
125-
1. Register a client:
126-
```bash
127-
basic-memory auth register-client
128-
```
129-
Copy the returned `client_id` and `client_secret`.
130-
131-
2. Follow the OAuth flow described below with the correct callback URL (`http://localhost:8000/auth/callback`).
132-
133-
## Testing with cURL
134-
135-
1. **Get authorization code**:
136-
```bash
137-
curl "http://localhost:8000/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:8000/auth/callback&response_type=code&code_challenge=test"
138-
```
139-
140-
2. **Exchange for token**:
141-
```bash
142-
curl -X POST http://localhost:8000/token \
143-
-H "Content-Type: application/x-www-form-urlencoded" \
144-
-d "grant_type=authorization_code&code=AUTH_CODE&client_id=CLIENT_ID&client_secret=CLIENT_SECRET"
145-
```
146-
147-
3. **Use the token**:
148-
```bash
149-
curl http://localhost:8000/mcp \
150-
-H "Authorization: Bearer ACCESS_TOKEN"
151-
```
152-
153-
## Quick Test Script
154-
155-
```python
156-
import httpx
157-
import asyncio
158-
from urllib.parse import urlparse, parse_qs
159-
160-
async def test_oauth():
161-
# Your client credentials
162-
client_id = "YOUR_CLIENT_ID"
163-
client_secret = "YOUR_CLIENT_SECRET"
164-
165-
async with httpx.AsyncClient() as client:
166-
# 1. Get authorization URL
167-
auth_response = await client.get(
168-
"http://localhost:8000/authorize",
169-
params={
170-
"client_id": client_id,
171-
"redirect_uri": "http://localhost:8000/auth/callback",
172-
"response_type": "code",
173-
"code_challenge": "test-challenge",
174-
"code_challenge_method": "S256",
175-
}
176-
)
177-
178-
# Extract code from redirect
179-
redirect_url = auth_response.headers.get("Location")
180-
parsed = urlparse(redirect_url)
181-
code = parse_qs(parsed.query)["code"][0]
182-
183-
# 2. Exchange code for tokens
184-
token_response = await client.post(
185-
"http://localhost:8000/token",
186-
data={
187-
"grant_type": "authorization_code",
188-
"code": code,
189-
"client_id": client_id,
190-
"client_secret": client_secret,
191-
"code_verifier": "test-verifier",
192-
}
193-
)
194-
tokens = token_response.json()
195-
196-
# 3. Use access token
197-
mcp_response = await client.get(
198-
"http://localhost:8000/mcp",
199-
headers={"Authorization": f"Bearer {tokens['access_token']}"}
200-
)
201-
202-
print(f"MCP Response: {mcp_response.status_code}")
203-
204-
asyncio.run(test_oauth())
18+
# 4. Copy the access token and use in MCP Inspector:
19+
# - Server URL: http://localhost:8000/mcp
20+
# - Transport: streamable-http
21+
# - Custom Headers:
22+
# Authorization: Bearer YOUR_ACCESS_TOKEN
23+
# Accept: application/json, text/event-stream
20524
```
20625

207-
## Connecting from Claude.ai
208-
209-
To connect your Basic Memory MCP server to Claude.ai:
210-
211-
1. **Deploy your MCP server** with OAuth enabled:
212-
```bash
213-
# Must use streamable-http transport
214-
FASTMCP_AUTH_ENABLED=true basic-memory mcp --transport streamable-http --host 0.0.0.0
215-
```
216-
217-
2. **Make server accessible** (for testing):
218-
- Use a tunneling service like ngrok: `ngrok http 8000`
219-
- Or deploy to a cloud provider
220-
- Note the public URL (e.g., `https://xyz.ngrok.io`)
221-
222-
3. **In Claude.ai**:
223-
- Go to **Settings****Integrations**
224-
- Click **Add More**
225-
- Enter your MCP server URL: `https://your-server.com/mcp`
226-
- Click **Connect**
227-
228-
4. **OAuth Flow**:
229-
- Claude will redirect you to your MCP server's authorization page
230-
- Login/authorize (depends on your provider)
231-
- You'll be redirected back to Claude
232-
- Claude now has access to your MCP server!
233-
234-
5. **Use in conversation**:
235-
- Click the tools icon (second from bottom left)
236-
- Select your Basic Memory server
237-
- Use commands like "write a note" or "search my notes"
238-
239-
## Provider Options
26+
## OAuth Endpoints
24027

241-
- **basic**: Built-in provider (development only)
242-
- **supabase**: Supabase Auth (recommended for production)
243-
- **github**: GitHub OAuth
244-
- **google**: Google OAuth
28+
- `GET /authorize` - Authorization endpoint
29+
- `POST /token` - Token exchange endpoint
30+
- `GET /.well-known/oauth-authorization-server` - OAuth metadata
24531

246-
## Debug Tips
32+
## Common Issues
24733

248-
- Check server logs for OAuth messages
249-
- Basic provider stores in memory (lost on restart)
250-
- Enable debug logging: `export FASTMCP_LOG_LEVEL=DEBUG`
34+
1. **401 Unauthorized**: Make sure you're using the same secret key for both server and client
35+
2. **404 Not Found**: Use `/authorize` not `/auth/authorize`
36+
3. **Token Invalid**: Tokens don't persist across server restarts with basic provider
25137

25238
## Documentation
25339

254-
- [OAuth Authentication Guide](docs/OAuth%20Authentication.md)
255-
- [Supabase OAuth Setup](docs/Supabase%20OAuth%20Setup.md)
256-
- [MCP Authorization Spec](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization)
257-
258-
259-
## CLAUDE OAUTH
260-
261-
⏺ Summary
262-
263-
Yes! Basic Memory now supports OAuth authentication that works with Claude.ai, just like claude-code. Here's what I've implemented:
264-
265-
1. OAuth Flow for Claude.ai
266-
267-
- Claude initiates the OAuth flow when connecting to your MCP server
268-
- The server handles authorization, token exchange, and validation
269-
- Full compliance with MCP OAuth 2.1 specification
270-
271-
2. Key Components Added
272-
273-
- OAuth authorization endpoints (/auth/authorize, /auth/token)
274-
- OAuth metadata discovery (/.well-known/oauth-authorization-server)
275-
- Support for PKCE (required by Claude)
276-
- Token refresh and revocation
277-
278-
3. How to Connect from Claude.ai
279-
280-
For testing locally:
281-
# 1. Enable OAuth
282-
export FASTMCP_AUTH_ENABLED=true
283-
284-
# 2. Start server
285-
basic-memory mcp --transport streamable-http --host 0.0.0.0
286-
287-
# 3. Make it accessible (use ngrok for testing)
288-
ngrok http 8000
289-
290-
# 4. In Claude.ai:
291-
# Settings → Integrations → Add More
292-
# Enter: https://your-ngrok-url.ngrok.io/mcp
293-
# Click Connect → Authorize
294-
295-
4. Production Setup
296-
297-
- Use Supabase provider for production
298-
- Deploy to HTTPS (required for OAuth)
299-
- Claude.ai Enterprise can add for entire organization
300-
301-
5. Security Features
302-
303-
- Scoped access (read, write, admin)
304-
- Short-lived tokens
305-
- Secure token storage
306-
- HTTPS required
307-
308-
The implementation follows the same pattern as claude-code, where:
309-
1. User adds the MCP server URL in Claude settings
310-
2. Claude redirects to your authorization endpoint
311-
3. User logs in and authorizes
312-
4. Claude receives tokens and can access your MCP tools
313-
314-
This enables persistent memory and knowledge management directly within Claude.ai conversations!
40+
- [OAuth Authentication Guide](docs/OAuth%20Authentication%20Guide.md) - Complete setup guide
41+
- [Supabase OAuth Setup](docs/Supabase%20OAuth%20Setup.md) - Production deployment
42+
- [External OAuth Providers](docs/External%20OAuth%20Providers.md) - GitHub, Google integration

0 commit comments

Comments
 (0)