@prmichaelsen/mcp-auth 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +220 -75
- package/dist/auth/base-provider.d.ts +85 -0
- package/dist/auth/base-provider.d.ts.map +1 -0
- package/dist/auth/index.d.ts +7 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +7 -1
- package/dist/auth/index.js.map +2 -2
- package/dist/auth/providers/api-token-resolver.d.ts +110 -0
- package/dist/auth/providers/api-token-resolver.d.ts.map +1 -0
- package/dist/auth/providers/api-token-resolver.js +225 -0
- package/dist/auth/providers/api-token-resolver.js.map +7 -0
- package/dist/auth/providers/env-provider.d.ts +65 -0
- package/dist/auth/providers/env-provider.d.ts.map +1 -0
- package/dist/auth/providers/index.d.ts +9 -0
- package/dist/auth/providers/index.d.ts.map +1 -0
- package/dist/auth/providers/index.js +12 -0
- package/dist/auth/providers/index.js.map +2 -2
- package/dist/auth/providers/jwt-provider.d.ts +133 -0
- package/dist/auth/providers/jwt-provider.d.ts.map +1 -0
- package/dist/auth/providers/jwt-provider.js +136 -0
- package/dist/auth/providers/jwt-provider.js.map +7 -0
- package/dist/auth/providers/jwt-token-resolver.d.ts +84 -0
- package/dist/auth/providers/jwt-token-resolver.d.ts.map +1 -0
- package/dist/auth/providers/jwt-token-resolver.js +94 -0
- package/dist/auth/providers/jwt-token-resolver.js.map +7 -0
- package/dist/auth/providers/simple-resolver.d.ts +109 -0
- package/dist/auth/providers/simple-resolver.d.ts.map +1 -0
- package/dist/auth/types.d.ts +215 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -1
- package/dist/index.js.map +2 -2
- package/dist/server/config.d.ts +90 -0
- package/dist/server/config.d.ts.map +1 -0
- package/dist/server/decorators.d.ts +136 -0
- package/dist/server/decorators.d.ts.map +1 -0
- package/dist/server/index.d.ts +10 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/mcp-server.d.ts +122 -0
- package/dist/server/mcp-server.d.ts.map +1 -0
- package/dist/server/tool.d.ts +120 -0
- package/dist/server/tool.d.ts.map +1 -0
- package/dist/types.d.ts +202 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/errors.d.ts +116 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +94 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/validation.d.ts +70 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/wrapper/config.d.ts +158 -0
- package/dist/wrapper/config.d.ts.map +1 -0
- package/dist/wrapper/index.d.ts +36 -0
- package/dist/wrapper/index.d.ts.map +1 -0
- package/dist/wrapper/server-wrapper.d.ts +103 -0
- package/dist/wrapper/server-wrapper.d.ts.map +1 -0
- package/dist/wrapper/server-wrapper.js.map +2 -2
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -6,42 +6,60 @@ Authentication and multi-tenancy framework for MCP (Model Context Protocol) serv
|
|
|
6
6
|
|
|
7
7
|
`@prmichaelsen/mcp-auth` provides a pluggable authentication system for MCP servers, enabling:
|
|
8
8
|
|
|
9
|
+
- **Zero modification**: Wrap existing MCP servers without code changes
|
|
9
10
|
- **Multi-tenancy**: Multiple users with separate resource tokens
|
|
10
|
-
- **Auth-agnostic**: Support for JWT,
|
|
11
|
+
- **Auth-agnostic**: Support for JWT, environment variables, or custom auth schemes
|
|
11
12
|
- **Transport-agnostic**: Works with stdio, HTTP, and SSE transports
|
|
12
13
|
- **Type-safe**: Full TypeScript support
|
|
13
|
-
- **Composable**: Middleware for rate limiting, logging,
|
|
14
|
+
- **Composable**: Middleware for rate limiting, logging, timeouts, retries
|
|
14
15
|
|
|
15
|
-
##
|
|
16
|
+
## Two Patterns
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
### Pattern 1: Server Wrapping (Recommended for Production)
|
|
19
|
+
|
|
20
|
+
Wrap existing MCP servers without modification:
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { wrapServer, JWTAuthProvider, APITokenResolver } from '@prmichaelsen/mcp-auth';
|
|
24
|
+
import { createServer } from '@myorg/my-mcp-server';
|
|
25
|
+
|
|
26
|
+
const wrapped = wrapServer({
|
|
27
|
+
serverFactory: createServer,
|
|
28
|
+
|
|
29
|
+
// Validates JWT from tenant manager
|
|
30
|
+
authProvider: new JWTAuthProvider({
|
|
31
|
+
jwtSecret: process.env.JWT_SECRET
|
|
32
|
+
}),
|
|
33
|
+
|
|
34
|
+
// Resolves tokens via tenant manager API (recommended)
|
|
35
|
+
tokenResolver: new APITokenResolver({
|
|
36
|
+
tenantManagerUrl: process.env.TENANT_MANAGER_URL,
|
|
37
|
+
serviceToken: process.env.SERVICE_TOKEN
|
|
38
|
+
}),
|
|
39
|
+
|
|
40
|
+
resourceType: 'myapi',
|
|
41
|
+
transport: { type: 'sse', port: 3000 }
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
await wrapped.start();
|
|
19
45
|
```
|
|
20
46
|
|
|
21
|
-
|
|
47
|
+
### Pattern 2: Tool-Level Auth
|
|
22
48
|
|
|
23
|
-
|
|
49
|
+
Build new servers with integrated authentication:
|
|
24
50
|
|
|
25
51
|
```typescript
|
|
26
|
-
import { withAuth,
|
|
27
|
-
import { EnvAuthProvider, SimpleTokenResolver } from '@prmichaelsen/mcp-auth/providers/env';
|
|
28
|
-
|
|
29
|
-
// Setup auth provider
|
|
30
|
-
const authProvider = new EnvAuthProvider();
|
|
31
|
-
const tokenResolver = new SimpleTokenResolver({ tokenEnvVar: 'API_TOKEN' });
|
|
52
|
+
import { AuthenticatedMCPServer, withAuth, EnvAuthProvider, SimpleTokenResolver } from '@prmichaelsen/mcp-auth';
|
|
32
53
|
|
|
33
|
-
// Create server
|
|
34
54
|
const server = new AuthenticatedMCPServer({
|
|
35
|
-
name: 'my-
|
|
36
|
-
authProvider,
|
|
37
|
-
tokenResolver,
|
|
55
|
+
name: 'my-server',
|
|
56
|
+
authProvider: new EnvAuthProvider(),
|
|
57
|
+
tokenResolver: new SimpleTokenResolver({ tokenEnvVar: 'API_TOKEN' }),
|
|
38
58
|
resourceType: 'myapi',
|
|
39
59
|
transport: { type: 'stdio' }
|
|
40
60
|
});
|
|
41
61
|
|
|
42
|
-
// Register tool with automatic auth
|
|
43
62
|
server.registerTool('get_data', withAuth(async (args, accessToken, userId) => {
|
|
44
|
-
// accessToken and userId are automatically injected
|
|
45
63
|
const client = new MyAPIClient(accessToken);
|
|
46
64
|
return client.getData(args);
|
|
47
65
|
}));
|
|
@@ -49,77 +67,123 @@ server.registerTool('get_data', withAuth(async (args, accessToken, userId) => {
|
|
|
49
67
|
await server.start();
|
|
50
68
|
```
|
|
51
69
|
|
|
52
|
-
|
|
70
|
+
## Installation
|
|
53
71
|
|
|
54
|
-
```
|
|
55
|
-
|
|
72
|
+
```bash
|
|
73
|
+
# Core package
|
|
74
|
+
npm install @prmichaelsen/mcp-auth @modelcontextprotocol/sdk
|
|
56
75
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
description = 'Fetch data from API';
|
|
60
|
-
|
|
61
|
-
async execute(args, accessToken, userId) {
|
|
62
|
-
const client = new MyAPIClient(accessToken);
|
|
63
|
-
return client.getData(args);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
76
|
+
# For JWT support
|
|
77
|
+
npm install jsonwebtoken
|
|
66
78
|
|
|
67
|
-
|
|
79
|
+
# For SSE/HTTP transports
|
|
80
|
+
npm install express cors
|
|
68
81
|
```
|
|
69
82
|
|
|
70
83
|
## Authentication Providers
|
|
71
84
|
|
|
72
|
-
###
|
|
85
|
+
### EnvAuthProvider (Single-User)
|
|
86
|
+
|
|
87
|
+
For local development and single-user scenarios:
|
|
73
88
|
|
|
74
89
|
```typescript
|
|
75
|
-
import { EnvAuthProvider, SimpleTokenResolver } from '@prmichaelsen/mcp-auth
|
|
90
|
+
import { EnvAuthProvider, SimpleTokenResolver } from '@prmichaelsen/mcp-auth';
|
|
76
91
|
|
|
77
|
-
const authProvider = new EnvAuthProvider(
|
|
78
|
-
|
|
92
|
+
const authProvider = new EnvAuthProvider({
|
|
93
|
+
userIdEnvVar: 'MCP_USER_ID',
|
|
94
|
+
defaultUserId: 'local-user'
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const tokenResolver = new SimpleTokenResolver({
|
|
98
|
+
tokenEnvVar: 'API_TOKEN'
|
|
99
|
+
});
|
|
79
100
|
```
|
|
80
101
|
|
|
81
|
-
###
|
|
102
|
+
### JWTAuthProvider + APITokenResolver (Multi-Tenant Production) ⭐ RECOMMENDED
|
|
103
|
+
|
|
104
|
+
For production multi-tenant deployments:
|
|
82
105
|
|
|
83
106
|
```typescript
|
|
84
|
-
import { JWTAuthProvider } from '@prmichaelsen/mcp-auth
|
|
107
|
+
import { JWTAuthProvider, APITokenResolver } from '@prmichaelsen/mcp-auth';
|
|
85
108
|
|
|
109
|
+
// Validates JWT tokens from tenant manager
|
|
86
110
|
const authProvider = new JWTAuthProvider({
|
|
87
111
|
jwtSecret: process.env.JWT_SECRET,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
112
|
+
userIdClaim: 'sub'
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Resolves tokens via tenant manager API
|
|
116
|
+
const tokenResolver = new APITokenResolver({
|
|
117
|
+
tenantManagerUrl: 'https://tenant-manager.example.com',
|
|
118
|
+
serviceToken: process.env.SERVICE_TOKEN,
|
|
119
|
+
cacheTokens: true, // Cache for performance
|
|
120
|
+
cacheTtl: 300000 // 5 minutes
|
|
92
121
|
});
|
|
93
122
|
```
|
|
94
123
|
|
|
95
|
-
|
|
124
|
+
**Why API-Based is Better:**
|
|
125
|
+
- ✅ Automatic token refresh (no new JWT needed)
|
|
126
|
+
- ✅ Immediate token revocation
|
|
127
|
+
- ✅ Tokens not exposed in JWT
|
|
128
|
+
- ✅ Small JWT size (~200 bytes)
|
|
129
|
+
- ✅ Centralized token management
|
|
130
|
+
|
|
131
|
+
### JWTAuthProvider + JWTTokenResolver (MVP/Prototyping)
|
|
132
|
+
|
|
133
|
+
For quick setup with JWT-embedded tokens:
|
|
96
134
|
|
|
97
135
|
```typescript
|
|
98
|
-
import {
|
|
136
|
+
import { JWTAuthProvider, JWTTokenResolver } from '@prmichaelsen/mcp-auth';
|
|
99
137
|
|
|
100
|
-
const authProvider = new
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
138
|
+
const authProvider = new JWTAuthProvider({
|
|
139
|
+
jwtSecret: process.env.JWT_SECRET,
|
|
140
|
+
extractTokens: true // Extract tokens from JWT
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const tokenResolver = new JWTTokenResolver({ authProvider });
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Trade-offs:**
|
|
147
|
+
- ✅ Zero API calls (faster)
|
|
148
|
+
- ✅ Simpler to implement
|
|
149
|
+
- ❌ Token rotation requires new JWT
|
|
150
|
+
- ❌ Larger JWT size
|
|
151
|
+
- ❌ Tokens exposed in JWT payload
|
|
152
|
+
|
|
153
|
+
### APITokenResolver (API-Based)
|
|
154
|
+
|
|
155
|
+
For resolving tokens via tenant manager API:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { JWTAuthProvider, APITokenResolver } from '@prmichaelsen/mcp-auth';
|
|
159
|
+
|
|
160
|
+
const authProvider = new JWTAuthProvider({
|
|
161
|
+
jwtSecret: process.env.JWT_SECRET
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const tokenResolver = new APITokenResolver({
|
|
165
|
+
tenantManagerUrl: 'https://tenant-manager.example.com',
|
|
166
|
+
serviceToken: process.env.SERVICE_TOKEN,
|
|
167
|
+
endpointPath: '/api/credentials/:userId/:resourceType'
|
|
105
168
|
});
|
|
106
169
|
```
|
|
107
170
|
|
|
108
171
|
### Custom Provider
|
|
109
172
|
|
|
173
|
+
Implement your own authentication logic:
|
|
174
|
+
|
|
110
175
|
```typescript
|
|
111
176
|
import { AuthProvider, AuthResult, RequestContext } from '@prmichaelsen/mcp-auth';
|
|
112
177
|
|
|
113
178
|
class CustomAuthProvider implements AuthProvider {
|
|
114
179
|
async authenticate(context: RequestContext): Promise<AuthResult> {
|
|
115
|
-
// Your custom auth logic
|
|
116
180
|
const apiKey = context.headers?.['x-api-key'];
|
|
117
181
|
|
|
118
182
|
if (!apiKey) {
|
|
119
183
|
return { authenticated: false, error: 'No API key' };
|
|
120
184
|
}
|
|
121
185
|
|
|
122
|
-
//
|
|
186
|
+
// Your validation logic
|
|
123
187
|
return {
|
|
124
188
|
authenticated: true,
|
|
125
189
|
userId: 'user-123'
|
|
@@ -131,11 +195,12 @@ class CustomAuthProvider implements AuthProvider {
|
|
|
131
195
|
## Middleware Composition
|
|
132
196
|
|
|
133
197
|
```typescript
|
|
134
|
-
import { compose, withAuth, withRateLimit, withLogging } from '@prmichaelsen/mcp-auth';
|
|
198
|
+
import { compose, withAuth, withRateLimit, withLogging, withTimeout } from '@prmichaelsen/mcp-auth';
|
|
135
199
|
|
|
136
200
|
const getTool = compose(
|
|
137
|
-
withLogging(),
|
|
201
|
+
withLogging({ logArgs: true }),
|
|
138
202
|
withRateLimit({ maxRequests: 100, windowMs: 60000 }),
|
|
203
|
+
withTimeout(5000),
|
|
139
204
|
withAuth(),
|
|
140
205
|
async (args, accessToken, userId) => {
|
|
141
206
|
// Your tool logic
|
|
@@ -150,41 +215,121 @@ server.registerTool('get_data', getTool);
|
|
|
150
215
|
### Stdio (Local)
|
|
151
216
|
|
|
152
217
|
```typescript
|
|
153
|
-
|
|
154
|
-
// ...
|
|
155
|
-
transport: { type: 'stdio' }
|
|
156
|
-
});
|
|
218
|
+
transport: { type: 'stdio' }
|
|
157
219
|
```
|
|
158
220
|
|
|
159
|
-
###
|
|
221
|
+
### SSE (Remote Multi-Tenant)
|
|
160
222
|
|
|
161
223
|
```typescript
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
224
|
+
transport: {
|
|
225
|
+
type: 'sse',
|
|
226
|
+
port: 3000,
|
|
227
|
+
host: '0.0.0.0',
|
|
228
|
+
basePath: '/mcp',
|
|
229
|
+
cors: true
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### HTTP (Remote)
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
transport: {
|
|
237
|
+
type: 'http',
|
|
238
|
+
port: 3000,
|
|
239
|
+
host: '0.0.0.0'
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## MCP Server Contract
|
|
244
|
+
|
|
245
|
+
To make your MCP server compatible with `wrapServer()`, export a factory function:
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
249
|
+
|
|
250
|
+
export function createServer(accessToken: string, userId?: string): Server {
|
|
251
|
+
const server = new Server({ name: 'my-server', version: '1.0.0' });
|
|
252
|
+
const client = new MyAPIClient(accessToken);
|
|
253
|
+
|
|
254
|
+
// Register your tool handlers...
|
|
255
|
+
|
|
256
|
+
return server;
|
|
257
|
+
}
|
|
171
258
|
```
|
|
172
259
|
|
|
260
|
+
That's it! No mcp-auth imports needed in your server.
|
|
261
|
+
|
|
262
|
+
## Architecture
|
|
263
|
+
|
|
264
|
+
### Three-Tier Deployment
|
|
265
|
+
|
|
266
|
+
1. **Chat Platform** - Sends MCP requests with JWT
|
|
267
|
+
2. **Tenant Manager** - Issues JWTs, manages user credentials
|
|
268
|
+
3. **MCP Server Instance** - Uses mcp-auth to wrap MCP servers
|
|
269
|
+
|
|
270
|
+
### Token Resolution Approaches
|
|
271
|
+
|
|
272
|
+
**Approach 1: JWT with Embedded Tokens** (Recommended)
|
|
273
|
+
- Tenant manager includes resource tokens in JWT
|
|
274
|
+
- Zero external calls
|
|
275
|
+
- Fastest performance
|
|
276
|
+
|
|
277
|
+
**Approach 2: API-Based Resolution**
|
|
278
|
+
- Tenant manager provides API for token lookup
|
|
279
|
+
- Better separation of concerns
|
|
280
|
+
- Easier token rotation
|
|
281
|
+
|
|
282
|
+
See [`agent/token-resolution-approaches.md`](./agent/token-resolution-approaches.md) for details.
|
|
283
|
+
|
|
173
284
|
## Documentation
|
|
174
285
|
|
|
175
|
-
|
|
286
|
+
Comprehensive architecture documentation in [`agent/`](./agent/):
|
|
176
287
|
|
|
177
|
-
- [`
|
|
178
|
-
- [`
|
|
179
|
-
- [`
|
|
288
|
+
- [`server-wrapping-pattern.md`](./agent/server-wrapping-pattern.md) - Server wrapping architecture
|
|
289
|
+
- [`server-contract.md`](./agent/server-contract.md) - MCP server compatibility guide
|
|
290
|
+
- [`dual-pattern-architecture.md`](./agent/dual-pattern-architecture.md) - Both patterns explained
|
|
291
|
+
- [`token-resolution-approaches.md`](./agent/token-resolution-approaches.md) - Token resolution strategies
|
|
292
|
+
- [`why-two-steps.md`](./agent/why-two-steps.md) - AuthProvider vs TokenResolver
|
|
293
|
+
- [`INTEGRATION.md`](./INTEGRATION.md) - Integration guide for MCP server authors
|
|
180
294
|
|
|
181
295
|
## Examples
|
|
182
296
|
|
|
183
|
-
|
|
297
|
+
Working examples coming soon in [`examples/`](./examples/):
|
|
184
298
|
|
|
185
299
|
- `simple-stdio/` - Single-user stdio server
|
|
186
|
-
- `
|
|
187
|
-
- `
|
|
300
|
+
- `wrapped-server/` - Server wrapping with JWT
|
|
301
|
+
- `tool-level-auth/` - Tool-level authentication
|
|
302
|
+
- `jwt-multi-tenant/` - Multi-tenant JWT deployment
|
|
303
|
+
|
|
304
|
+
## API Reference
|
|
305
|
+
|
|
306
|
+
### Core Functions
|
|
307
|
+
|
|
308
|
+
- `wrapServer(config)` - Wrap MCP server with authentication
|
|
309
|
+
- `withAuth(handler)` - Add auth to function-based tools
|
|
310
|
+
- `compose(...middlewares)` - Compose middleware functions
|
|
311
|
+
|
|
312
|
+
### Classes
|
|
313
|
+
|
|
314
|
+
- `AuthenticatedMCPServer` - MCP server with integrated auth
|
|
315
|
+
- `AuthenticatedTool` - Wrapper for class-based tools
|
|
316
|
+
- `BaseAuthProvider` - Base class for auth providers
|
|
317
|
+
|
|
318
|
+
### Providers
|
|
319
|
+
|
|
320
|
+
- `EnvAuthProvider` - Environment variable authentication
|
|
321
|
+
- `SimpleTokenResolver` - Environment variable token resolution
|
|
322
|
+
- `JWTAuthProvider` - JWT validation with token extraction
|
|
323
|
+
- `JWTTokenResolver` - JWT-embedded token resolution
|
|
324
|
+
- `APITokenResolver` - API-based token resolution
|
|
325
|
+
|
|
326
|
+
### Middleware
|
|
327
|
+
|
|
328
|
+
- `withAuth()` - Authentication
|
|
329
|
+
- `withLogging()` - Request/response logging
|
|
330
|
+
- `withRateLimit()` - Rate limiting per user
|
|
331
|
+
- `withTimeout()` - Request timeout
|
|
332
|
+
- `withRetry()` - Automatic retry on failure
|
|
188
333
|
|
|
189
334
|
## License
|
|
190
335
|
|
|
@@ -192,4 +337,4 @@ MIT
|
|
|
192
337
|
|
|
193
338
|
## Contributing
|
|
194
339
|
|
|
195
|
-
Contributions welcome! Please
|
|
340
|
+
Contributions welcome! Please open an issue or PR on [GitHub](https://github.com/prmichaelsen/mcp-auth).
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base authentication provider implementation
|
|
3
|
+
*
|
|
4
|
+
* Provides common functionality for authentication providers.
|
|
5
|
+
*/
|
|
6
|
+
import type { AuthProvider, AuthProviderConfig } from './types.js';
|
|
7
|
+
import type { RequestContext, AuthResult } from '../types.js';
|
|
8
|
+
import { type Logger } from '../utils/logger.js';
|
|
9
|
+
/**
|
|
10
|
+
* Abstract base class for authentication providers
|
|
11
|
+
*
|
|
12
|
+
* Provides common functionality like caching, logging, and error handling.
|
|
13
|
+
* Extend this class to implement custom authentication logic.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* class MyAuthProvider extends BaseAuthProvider {
|
|
18
|
+
* protected async doAuthenticate(context: RequestContext): Promise<AuthResult> {
|
|
19
|
+
* // Your authentication logic here
|
|
20
|
+
* return { authenticated: true, userId: 'user-123' };
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare abstract class BaseAuthProvider implements AuthProvider {
|
|
26
|
+
protected config: AuthProviderConfig;
|
|
27
|
+
protected logger: Logger;
|
|
28
|
+
private authCache;
|
|
29
|
+
constructor(config?: AuthProviderConfig);
|
|
30
|
+
/**
|
|
31
|
+
* Authenticate a request
|
|
32
|
+
* Implements caching if enabled
|
|
33
|
+
*/
|
|
34
|
+
authenticate(context: RequestContext): Promise<AuthResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Abstract method to implement authentication logic
|
|
37
|
+
* Override this in your provider implementation
|
|
38
|
+
*/
|
|
39
|
+
protected abstract doAuthenticate(context: RequestContext): Promise<AuthResult>;
|
|
40
|
+
/**
|
|
41
|
+
* Generate cache key from request context
|
|
42
|
+
* Override this to customize caching behavior
|
|
43
|
+
*/
|
|
44
|
+
protected getCacheKey(context: RequestContext): string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Extract authorization header from context
|
|
47
|
+
*/
|
|
48
|
+
protected getAuthorizationHeader(context: RequestContext): string | null;
|
|
49
|
+
/**
|
|
50
|
+
* Extract bearer token from authorization header
|
|
51
|
+
*/
|
|
52
|
+
protected extractBearerToken(context: RequestContext): string | null;
|
|
53
|
+
/**
|
|
54
|
+
* Create authentication failure result
|
|
55
|
+
*/
|
|
56
|
+
protected createFailureResult(error: string): AuthResult;
|
|
57
|
+
/**
|
|
58
|
+
* Create authentication success result
|
|
59
|
+
*/
|
|
60
|
+
protected createSuccessResult(userId: string, metadata?: Record<string, unknown>): AuthResult;
|
|
61
|
+
/**
|
|
62
|
+
* Optional: Initialize the provider
|
|
63
|
+
*/
|
|
64
|
+
initialize(): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Optional: Cleanup resources
|
|
67
|
+
*/
|
|
68
|
+
cleanup(): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Optional: Validate provider configuration
|
|
71
|
+
*/
|
|
72
|
+
validate(): Promise<boolean>;
|
|
73
|
+
/**
|
|
74
|
+
* Clear authentication cache
|
|
75
|
+
*/
|
|
76
|
+
clearCache(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Get cache statistics
|
|
79
|
+
*/
|
|
80
|
+
getCacheStats(): {
|
|
81
|
+
size: number;
|
|
82
|
+
keys: string[];
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=base-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-provider.d.ts","sourceRoot":"","sources":["../../src/auth/base-provider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE/D;;;;;;;;;;;;;;;GAeG;AACH,8BAAsB,gBAAiB,YAAW,YAAY;IAC5D,SAAS,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACrC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,SAAS,CAAyD;gBAE9D,MAAM,GAAE,kBAAuB;IAgB3C;;;OAGG;IACG,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IA6DhE;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IAE/E;;;OAGG;IACH,SAAS,CAAC,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAS7D;;OAEG;IACH,SAAS,CAAC,sBAAsB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAcxE;;OAEG;IACH,SAAS,CAAC,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI;IAepE;;OAEG;IACH,SAAS,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAOxD;;OAEG;IACH,SAAS,CAAC,mBAAmB,CAC3B,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,UAAU;IAQb;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAOjC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAMlC;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;OAEG;IACH,aAAa,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE;CAMlD"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication module exports
|
|
3
|
+
*/
|
|
4
|
+
export type { AuthProvider, ResourceTokenResolver, AuthenticatedContext, AuthProviderConfig, TokenResolverConfig } from './types.js';
|
|
5
|
+
export { BaseAuthProvider } from './base-provider.js';
|
|
6
|
+
export { EnvAuthProvider, type EnvAuthProviderConfig, SimpleTokenResolver, type SimpleTokenResolverConfig, JWTAuthProvider, type JWTAuthProviderConfig, type JWTPayload, JWTTokenResolver, type JWTTokenResolverConfig, APITokenResolver, type APITokenResolverConfig } from './providers/index.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EACV,YAAY,EACZ,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,EAC1B,mBAAmB,EACnB,KAAK,yBAAyB,EAC9B,eAAe,EACf,KAAK,qBAAqB,EAC1B,KAAK,UAAU,EACf,gBAAgB,EAChB,KAAK,sBAAsB,EAC3B,gBAAgB,EAChB,KAAK,sBAAsB,EAC5B,MAAM,sBAAsB,CAAC"}
|
package/dist/auth/index.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { BaseAuthProvider } from "./base-provider.js";
|
|
2
2
|
import {
|
|
3
3
|
EnvAuthProvider,
|
|
4
|
-
SimpleTokenResolver
|
|
4
|
+
SimpleTokenResolver,
|
|
5
|
+
JWTAuthProvider,
|
|
6
|
+
JWTTokenResolver,
|
|
7
|
+
APITokenResolver
|
|
5
8
|
} from "./providers/index.js";
|
|
6
9
|
export {
|
|
10
|
+
APITokenResolver,
|
|
7
11
|
BaseAuthProvider,
|
|
8
12
|
EnvAuthProvider,
|
|
13
|
+
JWTAuthProvider,
|
|
14
|
+
JWTTokenResolver,
|
|
9
15
|
SimpleTokenResolver
|
|
10
16
|
};
|
|
11
17
|
//# sourceMappingURL=index.js.map
|
package/dist/auth/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/auth/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Authentication module exports\n */\n\n// Types\nexport type {\n AuthProvider,\n ResourceTokenResolver,\n AuthenticatedContext,\n AuthProviderConfig,\n TokenResolverConfig\n} from './types.js';\n\n// Base provider\nexport { BaseAuthProvider } from './base-provider.js';\n\n// Providers\nexport {\n EnvAuthProvider,\n type EnvAuthProviderConfig,\n SimpleTokenResolver,\n type SimpleTokenResolverConfig\n} from './providers/index.js';\n"],
|
|
5
|
-
"mappings": "AAcA,SAAS,wBAAwB;AAGjC;AAAA,EACE;AAAA,EAEA;AAAA,OAEK;",
|
|
4
|
+
"sourcesContent": ["/**\n * Authentication module exports\n */\n\n// Types\nexport type {\n AuthProvider,\n ResourceTokenResolver,\n AuthenticatedContext,\n AuthProviderConfig,\n TokenResolverConfig\n} from './types.js';\n\n// Base provider\nexport { BaseAuthProvider } from './base-provider.js';\n\n// Providers\nexport {\n EnvAuthProvider,\n type EnvAuthProviderConfig,\n SimpleTokenResolver,\n type SimpleTokenResolverConfig,\n JWTAuthProvider,\n type JWTAuthProviderConfig,\n type JWTPayload,\n JWTTokenResolver,\n type JWTTokenResolverConfig,\n APITokenResolver,\n type APITokenResolverConfig\n} from './providers/index.js';\n"],
|
|
5
|
+
"mappings": "AAcA,SAAS,wBAAwB;AAGjC;AAAA,EACE;AAAA,EAEA;AAAA,EAEA;AAAA,EAGA;AAAA,EAEA;AAAA,OAEK;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API-based token resolver
|
|
3
|
+
*
|
|
4
|
+
* Resolves tokens by calling the tenant manager's API.
|
|
5
|
+
* Alternative to JWT-embedded tokens for better separation.
|
|
6
|
+
*/
|
|
7
|
+
import type { ResourceTokenResolver, TokenResolverConfig } from '../types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for APITokenResolver
|
|
10
|
+
*/
|
|
11
|
+
export interface APITokenResolverConfig extends TokenResolverConfig {
|
|
12
|
+
/**
|
|
13
|
+
* Tenant manager API base URL
|
|
14
|
+
* @example 'https://tenant-manager.example.com'
|
|
15
|
+
*/
|
|
16
|
+
tenantManagerUrl: string;
|
|
17
|
+
/**
|
|
18
|
+
* Service token for authenticating MCP server → tenant manager requests
|
|
19
|
+
* This is a separate token from user JWTs
|
|
20
|
+
*/
|
|
21
|
+
serviceToken: string;
|
|
22
|
+
/**
|
|
23
|
+
* API endpoint path template
|
|
24
|
+
* @default '/api/credentials/:userId/:resourceType'
|
|
25
|
+
*
|
|
26
|
+
* Variables:
|
|
27
|
+
* - :userId - Will be replaced with actual user ID
|
|
28
|
+
* - :resourceType - Will be replaced with resource type
|
|
29
|
+
*/
|
|
30
|
+
endpointPath?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Request timeout in milliseconds
|
|
33
|
+
* @default 5000
|
|
34
|
+
*/
|
|
35
|
+
timeoutMs?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Whether to throw error if token is not found
|
|
38
|
+
* @default true
|
|
39
|
+
*/
|
|
40
|
+
throwOnMissing?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Whether to validate token format
|
|
43
|
+
* @default true
|
|
44
|
+
*/
|
|
45
|
+
validateToken?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Custom headers to include in API requests
|
|
48
|
+
*/
|
|
49
|
+
customHeaders?: Record<string, string>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* API token resolver
|
|
53
|
+
*
|
|
54
|
+
* Resolves tokens by calling the tenant manager's API endpoint.
|
|
55
|
+
* This approach provides better separation between MCP server and tenant manager.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const resolver = new APITokenResolver({
|
|
60
|
+
* tenantManagerUrl: 'https://tenant-manager.example.com',
|
|
61
|
+
* serviceToken: process.env.SERVICE_TOKEN
|
|
62
|
+
* });
|
|
63
|
+
*
|
|
64
|
+
* // Calls: GET https://tenant-manager.example.com/api/credentials/user-123/instagram
|
|
65
|
+
* // Headers: { Authorization: Bearer <service-token> }
|
|
66
|
+
* // Returns: { accessToken: "IGQVJXabc..." }
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare class APITokenResolver implements ResourceTokenResolver {
|
|
70
|
+
private config;
|
|
71
|
+
private logger;
|
|
72
|
+
private tokenCache;
|
|
73
|
+
constructor(config: APITokenResolverConfig);
|
|
74
|
+
/**
|
|
75
|
+
* Resolve token by calling tenant manager API
|
|
76
|
+
*/
|
|
77
|
+
resolveToken(userId: string, resourceType: string): Promise<string | null>;
|
|
78
|
+
/**
|
|
79
|
+
* Build API URL from template
|
|
80
|
+
*/
|
|
81
|
+
private buildUrl;
|
|
82
|
+
/**
|
|
83
|
+
* Refresh token (calls API again)
|
|
84
|
+
*/
|
|
85
|
+
refreshToken(userId: string, resourceType: string): Promise<string | null>;
|
|
86
|
+
/**
|
|
87
|
+
* Validate token (basic check)
|
|
88
|
+
*/
|
|
89
|
+
validateToken(token: string, resourceType: string): Promise<boolean>;
|
|
90
|
+
/**
|
|
91
|
+
* Initialize resolver
|
|
92
|
+
*/
|
|
93
|
+
initialize(): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Cleanup resources
|
|
96
|
+
*/
|
|
97
|
+
cleanup(): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Clear token cache
|
|
100
|
+
*/
|
|
101
|
+
clearCache(): void;
|
|
102
|
+
/**
|
|
103
|
+
* Get cache statistics
|
|
104
|
+
*/
|
|
105
|
+
getCacheStats(): {
|
|
106
|
+
size: number;
|
|
107
|
+
keys: string[];
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=api-token-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-token-resolver.d.ts","sourceRoot":"","sources":["../../../src/auth/providers/api-token-resolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAK9E;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,mBAAmB;IACjE;;;OAGG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,gBAAiB,YAAW,qBAAqB;IAC5D,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAoD;gBAE1D,MAAM,EAAE,sBAAsB;IAyB1C;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAqJhF;;OAEG;IACH,OAAO,CAAC,QAAQ;IAQhB;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUhF;;OAEG;IACG,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAa1E;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBjC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAK9B;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;OAEG;IACH,aAAa,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE;CAMlD"}
|