Skip to content

Commit 1aacf2b

Browse files
committed
auth wip
Signed-off-by: phernandez <paul@basicmachines.co>
1 parent cabf233 commit 1aacf2b

3 files changed

Lines changed: 84 additions & 13 deletions

File tree

AUTH.md

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,43 @@
22

33
This guide shows how to test OAuth authentication with Basic Memory MCP server, including how to connect from Claude.ai.
44

5+
## MCP Inspector Testing
6+
7+
To test with MCP Inspector when OAuth is enabled:
8+
9+
1. **Start the server with OAuth**:
10+
```bash
11+
FASTMCP_AUTH_ENABLED=true basic-memory mcp --transport streamable-http
12+
```
13+
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+
```
19+
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+
542
## Local Testing with Built-in Provider
643

744
1. **Create `.env` file**:
@@ -21,7 +58,7 @@ This guide shows how to test OAuth authentication with Basic Memory MCP server,
2158
basic-memory mcp --transport streamable-http
2259

2360
# Or directly
24-
FASTMCP_AUTH_ENABLED=true basic-memory mcp --transport streamable-http
61+
2562
```
2663

2764
4. **Register a client**:
@@ -57,15 +94,47 @@ This guide shows how to test OAuth authentication with Basic Memory MCP server,
5794

5895
When OAuth is enabled, these endpoints are available:
5996

60-
- `GET /authorize` - OAuth authorization endpoint
61-
- `POST /token` - Token exchange endpoint
97+
- `GET /auth/authorize` - OAuth authorization endpoint
98+
- `POST /auth/token` - Token exchange endpoint
6299
- `GET /mcp` - Protected MCP endpoint (requires Bearer token)
63100

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+
64133
## Testing with cURL
65134

66135
1. **Get authorization code**:
67136
```bash
68-
curl "http://localhost:8000/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:3000/callback&response_type=code&code_challenge=test"
137+
curl "http://localhost:8000/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:8000/auth/callback&response_type=code&code_challenge=test"
69138
```
70139

71140
2. **Exchange for token**:
@@ -99,7 +168,7 @@ async def test_oauth():
99168
"http://localhost:8000/authorize",
100169
params={
101170
"client_id": client_id,
102-
"redirect_uri": "http://localhost:3000/callback",
171+
"redirect_uri": "http://localhost:8000/auth/callback",
103172
"response_type": "code",
104173
"code_challenge": "test-challenge",
105174
"code_challenge_method": "S256",

src/basic_memory/cli/commands/auth.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@ def register_client(
2222
# Create provider instance
2323
provider = BasicMemoryOAuthProvider(issuer_url=issuer_url)
2424

25-
# Create client info
25+
# Create client info with required redirect_uris
2626
client_info = OAuthClientInformationFull(
2727
client_id=client_id,
2828
client_secret=client_secret,
29+
redirect_uris=["http://localhost:8000/auth/callback"], # Default redirect URI
30+
client_name="Basic Memory OAuth Client",
31+
grant_types=["authorization_code", "refresh_token"],
2932
)
3033

3134
# Register the client
@@ -57,6 +60,9 @@ async def test_flow():
5760
client_info = OAuthClientInformationFull(
5861
client_id=secrets.token_urlsafe(16),
5962
client_secret=secrets.token_urlsafe(32),
63+
redirect_uris=["http://localhost:8000/auth/callback"],
64+
client_name="Test OAuth Client",
65+
grant_types=["authorization_code", "refresh_token"],
6066
)
6167
await provider.register_client(client_info)
6268
typer.echo(f"Registered test client: {client_info.client_id}")
@@ -72,7 +78,7 @@ async def test_flow():
7278
state="test-state",
7379
scopes=["read", "write"],
7480
code_challenge="test-challenge",
75-
redirect_uri=AnyHttpUrl("http://localhost:3000/callback"),
81+
redirect_uri=AnyHttpUrl("http://localhost:8000/auth/callback"),
7682
redirect_uri_provided_explicitly=True,
7783
)
7884

@@ -98,8 +104,8 @@ async def test_flow():
98104

99105
# Exchange for tokens
100106
token = await provider.exchange_authorization_code(client, code_obj)
101-
typer.echo(f"Access token: {token.access_token[:20]}...")
102-
typer.echo(f"Refresh token: {token.refresh_token[:20]}...")
107+
typer.echo(f"Access token: {token.access_token}")
108+
typer.echo(f"Refresh token: {token.refresh_token}")
103109
typer.echo(f"Expires in: {token.expires_in} seconds")
104110

105111
# Validate access token

src/basic_memory/mcp/auth_provider.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""OAuth authentication provider for Basic Memory MCP server."""
22

33
import secrets
4-
from dataclasses import dataclass
54
from datetime import datetime, timedelta
65
from typing import Dict, Optional, Any
76

@@ -21,19 +20,16 @@
2120
from loguru import logger
2221

2322

24-
@dataclass
2523
class BasicMemoryAuthorizationCode(AuthorizationCode):
2624
"""Extended authorization code with additional metadata."""
2725
issuer_state: Optional[str] = None
2826

2927

30-
@dataclass
3128
class BasicMemoryRefreshToken(RefreshToken):
3229
"""Extended refresh token with additional metadata."""
3330
pass
3431

3532

36-
@dataclass
3733
class BasicMemoryAccessToken(AccessToken):
3834
"""Extended access token with additional metadata."""
3935
pass

0 commit comments

Comments
 (0)