Skip to content

Commit c4c5903

Browse files
RahulHereRahulHere
authored andcommitted
temp: make gopher-auth just provides registerOAuthRoutes and expressMiddleware
1 parent f6662de commit c4c5903

File tree

14 files changed

+1401
-56
lines changed

14 files changed

+1401
-56
lines changed

include/mcp/auth/auth_c_api.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,18 @@ mcp_auth_error_t mcp_auth_validate_token(
197197
mcp_auth_validation_options_t options,
198198
mcp_auth_validation_result_t* result);
199199

200+
/**
201+
* @brief Validate a JWT token (returns result by value for FFI compatibility)
202+
* @param client Client handle
203+
* @param token JWT token string
204+
* @param options Validation options (can be NULL for defaults)
205+
* @return Validation result struct
206+
*/
207+
mcp_auth_validation_result_t mcp_auth_validate_token_ret(
208+
mcp_auth_client_t client,
209+
const char* token,
210+
mcp_auth_validation_options_t options);
211+
200212
/**
201213
* @brief Extract token payload without validation
202214
* @param token JWT token string

sdk/typescript/README-AUTH.md

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
# @mcp/filter-sdk Authentication
2+
3+
The @mcp/filter-sdk provides two usage patterns for authentication, making it compatible with different coding styles and requirements.
4+
5+
## Two Usage Patterns
6+
7+
### Pattern 1: Express-Style APIs (NEW)
8+
9+
Similar to `gopher-auth-sdk-nodejs`, this pattern provides explicit control through two main APIs:
10+
11+
1. **`registerOAuthRoutes(app, options)`** - Registers OAuth discovery and proxy endpoints
12+
2. **`expressMiddleware(options)`** - Creates authentication middleware for Express
13+
14+
```typescript
15+
import express from 'express';
16+
import { McpExpressAuth } from '@mcp/filter-sdk/auth';
17+
18+
const app = express();
19+
const auth = new McpExpressAuth();
20+
21+
// API 1: Register OAuth routes
22+
auth.registerOAuthRoutes(app, {
23+
serverUrl: 'http://localhost:3001',
24+
allowedScopes: ['mcp:weather', 'openid']
25+
});
26+
27+
// API 2: Use authentication middleware
28+
app.all('/mcp',
29+
auth.expressMiddleware({
30+
publicMethods: ['initialize'],
31+
toolScopes: {
32+
'get-forecast': ['mcp:weather']
33+
}
34+
}),
35+
mcpHandler
36+
);
37+
```
38+
39+
### Pattern 2: Simple AuthenticatedMcpServer (EXISTING)
40+
41+
The original pattern for quick setup with minimal configuration:
42+
43+
```typescript
44+
import { AuthenticatedMcpServer } from '@mcp/filter-sdk/auth';
45+
46+
const server = new AuthenticatedMcpServer();
47+
server.register(tools);
48+
await server.start();
49+
```
50+
51+
## Configuration
52+
53+
Both patterns support configuration through:
54+
- Constructor parameters
55+
- Environment variables
56+
- Mixed approach
57+
58+
### Environment Variables
59+
60+
```bash
61+
# OAuth Server Configuration
62+
GOPHER_AUTH_SERVER_URL=http://localhost:8080/realms/gopher-auth
63+
GOPHER_CLIENT_ID=mcp-server
64+
GOPHER_CLIENT_SECRET=secret
65+
66+
# Optional
67+
JWKS_URI=http://localhost:8080/realms/gopher-auth/protocol/openid-connect/certs
68+
TOKEN_ISSUER=http://localhost:8080/realms/gopher-auth
69+
TOKEN_AUDIENCE=mcp-server
70+
JWKS_CACHE_DURATION=3600
71+
REQUEST_TIMEOUT=10
72+
```
73+
74+
## Express Pattern Details
75+
76+
### registerOAuthRoutes
77+
78+
Creates these endpoints:
79+
- `/.well-known/oauth-protected-resource` - Protected resource metadata (RFC 9728)
80+
- `/.well-known/oauth-authorization-server` - OAuth metadata proxy (RFC 8414)
81+
- `/realms/:realm/clients-registrations/openid-connect` - Client registration proxy
82+
83+
Options:
84+
```typescript
85+
interface OAuthProxyOptions {
86+
serverUrl: string; // Your MCP server URL
87+
allowedScopes?: string[]; // Scopes to allow (default: ['openid'])
88+
}
89+
```
90+
91+
### expressMiddleware
92+
93+
Creates Express middleware for token validation:
94+
95+
Options:
96+
```typescript
97+
interface ExpressMiddlewareOptions {
98+
audience?: string | string[]; // Expected audience(s)
99+
publicPaths?: string[]; // Paths without auth
100+
publicMethods?: string[]; // MCP methods without auth
101+
toolScopes?: Record<string, string[]>; // Tool-specific scopes
102+
}
103+
```
104+
105+
## Complete Examples
106+
107+
### Express Pattern with Full Control
108+
109+
```typescript
110+
import express from 'express';
111+
import { McpExpressAuth } from '@mcp/filter-sdk/auth';
112+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
113+
114+
const app = express();
115+
app.use(express.json());
116+
117+
// Initialize auth
118+
const auth = new McpExpressAuth({
119+
issuer: 'http://localhost:8080/realms/gopher-auth',
120+
jwksUri: 'http://localhost:8080/realms/gopher-auth/protocol/openid-connect/certs',
121+
tokenAudience: 'mcp-server'
122+
});
123+
124+
// Register OAuth routes
125+
auth.registerOAuthRoutes(app, {
126+
serverUrl: 'http://localhost:3001',
127+
allowedScopes: ['mcp:weather', 'openid']
128+
});
129+
130+
// Create MCP server
131+
const mcpServer = new Server(
132+
{ name: 'weather-server', version: '1.0.0' },
133+
{ capabilities: { tools: {} } }
134+
);
135+
136+
// Protected MCP endpoint
137+
app.all('/mcp',
138+
auth.expressMiddleware({
139+
publicMethods: ['initialize'],
140+
toolScopes: {
141+
'get-forecast': ['mcp:weather'],
142+
'get-alerts': ['mcp:weather', 'mcp:admin']
143+
}
144+
}),
145+
async (req, res) => {
146+
const user = (req as any).auth;
147+
console.log('User:', user?.subject);
148+
// Handle MCP request
149+
await handleMcpRequest(req, res);
150+
}
151+
);
152+
153+
// Additional authenticated API
154+
app.get('/api/status',
155+
auth.expressMiddleware(),
156+
(req, res) => {
157+
const user = (req as any).auth;
158+
res.json({ user: user?.subject, status: 'ok' });
159+
}
160+
);
161+
162+
app.listen(3001);
163+
```
164+
165+
### Simple Pattern (Backward Compatible)
166+
167+
```typescript
168+
import { AuthenticatedMcpServer, Tool } from '@mcp/filter-sdk/auth';
169+
import dotenv from 'dotenv';
170+
171+
dotenv.config();
172+
173+
const tools: Tool[] = [
174+
{
175+
name: 'get-weather',
176+
description: 'Get weather',
177+
inputSchema: { /* ... */ },
178+
handler: async (req) => { /* ... */ }
179+
}
180+
];
181+
182+
// Simple setup - config from environment
183+
const server = new AuthenticatedMcpServer();
184+
server.register(tools);
185+
await server.start();
186+
```
187+
188+
### Hybrid Usage
189+
190+
You can use both patterns together:
191+
192+
```typescript
193+
import { AuthenticatedMcpServer, McpExpressAuth } from '@mcp/filter-sdk/auth';
194+
195+
// Use AuthenticatedMcpServer for MCP
196+
const mcpServer = new AuthenticatedMcpServer({
197+
transport: 'http',
198+
serverPort: 3001
199+
});
200+
mcpServer.register(tools);
201+
202+
// Also use Express auth for custom endpoints
203+
const auth = new McpExpressAuth();
204+
const app = express();
205+
206+
auth.registerOAuthRoutes(app, {
207+
serverUrl: 'http://localhost:3001',
208+
allowedScopes: ['mcp:weather']
209+
});
210+
211+
app.get('/custom-api',
212+
auth.expressMiddleware(),
213+
(req, res) => {
214+
// Custom authenticated endpoint
215+
}
216+
);
217+
```
218+
219+
## Migration Guide
220+
221+
### From No Auth to OAuth
222+
223+
Before:
224+
```typescript
225+
const server = new Server(...);
226+
// No authentication
227+
```
228+
229+
After (Simple):
230+
```typescript
231+
const server = new AuthenticatedMcpServer();
232+
// OAuth enabled
233+
```
234+
235+
After (Express):
236+
```typescript
237+
const auth = new McpExpressAuth();
238+
auth.registerOAuthRoutes(app, options);
239+
app.all('/mcp', auth.expressMiddleware(options), handler);
240+
```
241+
242+
### From gopher-auth-sdk-nodejs
243+
244+
The Express pattern APIs are designed to be similar:
245+
246+
gopher-auth-sdk-nodejs:
247+
```typescript
248+
const auth = new GopherAuth(config);
249+
auth.registerOAuthRoutes(app, options);
250+
app.all('/mcp', auth.expressMiddleware(options), handler);
251+
```
252+
253+
@mcp/filter-sdk:
254+
```typescript
255+
const auth = new McpExpressAuth(config);
256+
auth.registerOAuthRoutes(app, options);
257+
app.all('/mcp', auth.expressMiddleware(options), handler);
258+
```
259+
260+
## Benefits
261+
262+
- **Pattern 1 (Express)**: Full control, explicit configuration, custom endpoints
263+
- **Pattern 2 (Simple)**: Quick setup, convention over configuration, minimal code
264+
265+
Choose the pattern that best fits your needs. Both are fully supported and can be used together.

0 commit comments

Comments
 (0)