@leanmcp/auth 0.4.2 → 0.4.3
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/LICENSE +21 -21
- package/README.md +396 -396
- package/dist/client/index.d.mts +499 -0
- package/dist/client/index.d.ts +499 -0
- package/dist/index.d.mts +181 -0
- package/dist/index.d.ts +181 -0
- package/dist/proxy/index.d.mts +376 -0
- package/dist/proxy/index.d.ts +376 -0
- package/dist/server/index.d.mts +496 -0
- package/dist/server/index.d.ts +496 -0
- package/dist/storage/index.d.mts +181 -0
- package/dist/storage/index.d.ts +181 -0
- package/dist/types-DMpGN530.d.mts +122 -0
- package/dist/types-DMpGN530.d.ts +122 -0
- package/package.json +121 -120
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { T as TokenStorage, O as OAuthTokens } from '../types-DMpGN530.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PKCE (Proof Key for Code Exchange) utilities for OAuth 2.1
|
|
5
|
+
*
|
|
6
|
+
* RFC 7636: https://tools.ietf.org/html/rfc7636
|
|
7
|
+
*
|
|
8
|
+
* PKCE protects against authorization code interception attacks
|
|
9
|
+
* by using a cryptographic challenge during the OAuth flow.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* PKCE code challenge and verifier pair
|
|
13
|
+
*/
|
|
14
|
+
interface PKCEPair {
|
|
15
|
+
/** High-entropy random string (43-128 chars) */
|
|
16
|
+
verifier: string;
|
|
17
|
+
/** SHA256 hash of verifier, base64url encoded */
|
|
18
|
+
challenge: string;
|
|
19
|
+
/** Challenge method - always S256 for security */
|
|
20
|
+
method: 'S256';
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Generate a cryptographically secure PKCE code verifier.
|
|
24
|
+
*
|
|
25
|
+
* The verifier is a high-entropy random string between 43-128 characters
|
|
26
|
+
* using unreserved characters: [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
|
|
27
|
+
*
|
|
28
|
+
* @param length - Length of the verifier (default: 64, min: 43, max: 128)
|
|
29
|
+
* @returns Base64url-encoded random string
|
|
30
|
+
*/
|
|
31
|
+
declare function generateCodeVerifier(length?: number): string;
|
|
32
|
+
/**
|
|
33
|
+
* Generate a PKCE code challenge from a code verifier.
|
|
34
|
+
*
|
|
35
|
+
* Uses the S256 method: BASE64URL(SHA256(verifier))
|
|
36
|
+
*
|
|
37
|
+
* @param verifier - The code verifier string
|
|
38
|
+
* @returns Base64url-encoded SHA256 hash
|
|
39
|
+
*/
|
|
40
|
+
declare function generateCodeChallenge(verifier: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Generate a complete PKCE pair (verifier and challenge).
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const pkce = generatePKCE();
|
|
47
|
+
* // Send challenge in authorization request
|
|
48
|
+
* const authUrl = `${authorizationEndpoint}?code_challenge=${pkce.challenge}&code_challenge_method=S256`;
|
|
49
|
+
* // Send verifier in token request
|
|
50
|
+
* const tokenPayload = { code_verifier: pkce.verifier, ... };
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @param verifierLength - Length of the verifier (default: 64)
|
|
54
|
+
* @returns PKCE pair with verifier, challenge, and method
|
|
55
|
+
*/
|
|
56
|
+
declare function generatePKCE(verifierLength?: number): PKCEPair;
|
|
57
|
+
/**
|
|
58
|
+
* Verify that a code verifier matches a code challenge.
|
|
59
|
+
*
|
|
60
|
+
* Used server-side to validate PKCE during token exchange.
|
|
61
|
+
*
|
|
62
|
+
* @param verifier - The code verifier from token request
|
|
63
|
+
* @param challenge - The code challenge from authorization request
|
|
64
|
+
* @param method - The challenge method (only 'S256' supported)
|
|
65
|
+
* @returns True if verifier matches challenge
|
|
66
|
+
*/
|
|
67
|
+
declare function verifyPKCE(verifier: string, challenge: string, method?: 'S256' | 'plain'): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Validate that a string is a valid PKCE code verifier.
|
|
70
|
+
*
|
|
71
|
+
* @param verifier - String to validate
|
|
72
|
+
* @returns True if valid verifier format
|
|
73
|
+
*/
|
|
74
|
+
declare function isValidCodeVerifier(verifier: string): boolean;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* OAuth 2.1 Client for MCP
|
|
78
|
+
*
|
|
79
|
+
* Handles browser-based OAuth flows with PKCE support.
|
|
80
|
+
* Compatible with MCP servers and external OAuth providers.
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* OAuth client configuration
|
|
85
|
+
*/
|
|
86
|
+
interface OAuthClientOptions {
|
|
87
|
+
/** MCP server URL or OAuth authorization server URL */
|
|
88
|
+
serverUrl: string;
|
|
89
|
+
/** OAuth scopes to request */
|
|
90
|
+
scopes?: string[];
|
|
91
|
+
/** Client name for dynamic registration */
|
|
92
|
+
clientName?: string;
|
|
93
|
+
/** Token storage backend */
|
|
94
|
+
storage?: TokenStorage;
|
|
95
|
+
/** Pre-configured client credentials (skip dynamic registration) */
|
|
96
|
+
clientId?: string;
|
|
97
|
+
clientSecret?: string;
|
|
98
|
+
/** Custom OAuth endpoints (auto-discovered if not provided) */
|
|
99
|
+
authorizationEndpoint?: string;
|
|
100
|
+
tokenEndpoint?: string;
|
|
101
|
+
registrationEndpoint?: string;
|
|
102
|
+
/** Enable PKCE (default: true) */
|
|
103
|
+
pkceEnabled?: boolean;
|
|
104
|
+
/** Automatically refresh tokens before expiry (default: true) */
|
|
105
|
+
autoRefresh?: boolean;
|
|
106
|
+
/** Seconds before expiry to trigger refresh (default: 60) */
|
|
107
|
+
refreshBuffer?: number;
|
|
108
|
+
/** Callback server port (default: auto) */
|
|
109
|
+
callbackPort?: number;
|
|
110
|
+
/** OAuth timeout in ms (default: 5 minutes) */
|
|
111
|
+
timeout?: number;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* OAuth 2.1 client with PKCE and browser-based authentication
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* const client = new OAuthClient({
|
|
119
|
+
* serverUrl: 'https://mcp.example.com',
|
|
120
|
+
* scopes: ['read', 'write'],
|
|
121
|
+
* });
|
|
122
|
+
*
|
|
123
|
+
* // Start browser-based OAuth flow
|
|
124
|
+
* await client.authenticate();
|
|
125
|
+
*
|
|
126
|
+
* // Get token for API calls
|
|
127
|
+
* const token = await client.getValidToken();
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
declare class OAuthClient {
|
|
131
|
+
private serverUrl;
|
|
132
|
+
private scopes;
|
|
133
|
+
private clientName;
|
|
134
|
+
private storage;
|
|
135
|
+
private pkceEnabled;
|
|
136
|
+
private autoRefresh;
|
|
137
|
+
private refreshBuffer;
|
|
138
|
+
private callbackPort?;
|
|
139
|
+
private timeout;
|
|
140
|
+
private authorizationEndpoint?;
|
|
141
|
+
private tokenEndpoint?;
|
|
142
|
+
private registrationEndpoint?;
|
|
143
|
+
private preConfiguredClientId?;
|
|
144
|
+
private preConfiguredClientSecret?;
|
|
145
|
+
private pendingRefresh?;
|
|
146
|
+
private metadata?;
|
|
147
|
+
constructor(options: OAuthClientOptions);
|
|
148
|
+
/**
|
|
149
|
+
* Discover OAuth metadata from .well-known endpoint
|
|
150
|
+
*/
|
|
151
|
+
private discoverMetadata;
|
|
152
|
+
/**
|
|
153
|
+
* Get or register OAuth client credentials
|
|
154
|
+
*/
|
|
155
|
+
private getClientCredentials;
|
|
156
|
+
/**
|
|
157
|
+
* Start the browser-based OAuth flow
|
|
158
|
+
*
|
|
159
|
+
* Opens the user's browser to the authorization URL and waits for the callback.
|
|
160
|
+
*
|
|
161
|
+
* @returns OAuth tokens
|
|
162
|
+
*/
|
|
163
|
+
authenticate(): Promise<OAuthTokens>;
|
|
164
|
+
/**
|
|
165
|
+
* Open URL in browser
|
|
166
|
+
*/
|
|
167
|
+
private openBrowser;
|
|
168
|
+
/**
|
|
169
|
+
* Exchange authorization code for tokens
|
|
170
|
+
*/
|
|
171
|
+
private exchangeCodeForTokens;
|
|
172
|
+
/**
|
|
173
|
+
* Refresh the access token using the refresh token
|
|
174
|
+
*/
|
|
175
|
+
refreshTokens(): Promise<OAuthTokens>;
|
|
176
|
+
private doRefreshTokens;
|
|
177
|
+
/**
|
|
178
|
+
* Get a valid access token, refreshing if necessary
|
|
179
|
+
*/
|
|
180
|
+
getValidToken(): Promise<string>;
|
|
181
|
+
/**
|
|
182
|
+
* Get current tokens (may be expired)
|
|
183
|
+
*/
|
|
184
|
+
getTokens(): Promise<OAuthTokens | null>;
|
|
185
|
+
/**
|
|
186
|
+
* Check if we have valid (non-expired) tokens
|
|
187
|
+
*/
|
|
188
|
+
isAuthenticated(): Promise<boolean>;
|
|
189
|
+
/**
|
|
190
|
+
* Clear stored tokens and log out
|
|
191
|
+
*/
|
|
192
|
+
logout(): Promise<void>;
|
|
193
|
+
/**
|
|
194
|
+
* Create an auth handler for HTTP requests
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```typescript
|
|
198
|
+
* const authHandler = client.asAuthHandler();
|
|
199
|
+
* const authedRequest = await authHandler(request);
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
asAuthHandler(): (request: Request) => Promise<Request>;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Local HTTP callback server for OAuth redirects
|
|
207
|
+
*
|
|
208
|
+
* Spins up a temporary HTTP server to catch OAuth authorization callbacks.
|
|
209
|
+
* Used during browser-based OAuth flows.
|
|
210
|
+
*/
|
|
211
|
+
/**
|
|
212
|
+
* Result from OAuth callback
|
|
213
|
+
*/
|
|
214
|
+
interface CallbackResult {
|
|
215
|
+
/** Authorization code from the OAuth server */
|
|
216
|
+
code: string;
|
|
217
|
+
/** State parameter for CSRF protection */
|
|
218
|
+
state: string;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Error from OAuth callback
|
|
222
|
+
*/
|
|
223
|
+
interface CallbackError {
|
|
224
|
+
error: string;
|
|
225
|
+
error_description?: string;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Options for the callback server
|
|
229
|
+
*/
|
|
230
|
+
interface CallbackServerOptions {
|
|
231
|
+
/** Port to listen on (0 = auto-assign) */
|
|
232
|
+
port?: number;
|
|
233
|
+
/** Host to bind to (default: 127.0.0.1) */
|
|
234
|
+
host?: string;
|
|
235
|
+
/** Callback path (default: /callback) */
|
|
236
|
+
path?: string;
|
|
237
|
+
/** Timeout in milliseconds (default: 5 minutes) */
|
|
238
|
+
timeout?: number;
|
|
239
|
+
/** Custom success HTML */
|
|
240
|
+
successHtml?: string;
|
|
241
|
+
/** Custom error HTML */
|
|
242
|
+
errorHtml?: string;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Running callback server instance
|
|
246
|
+
*/
|
|
247
|
+
interface CallbackServer {
|
|
248
|
+
/** Full URL to use as redirect_uri */
|
|
249
|
+
redirectUri: string;
|
|
250
|
+
/** Port the server is listening on */
|
|
251
|
+
port: number;
|
|
252
|
+
/** Wait for the OAuth callback */
|
|
253
|
+
waitForCallback(): Promise<CallbackResult>;
|
|
254
|
+
/** Shutdown the server */
|
|
255
|
+
shutdown(): Promise<void>;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Start a local callback server for OAuth redirects
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```typescript
|
|
262
|
+
* const server = await startCallbackServer({ port: 0 });
|
|
263
|
+
* console.log('Redirect URI:', server.redirectUri);
|
|
264
|
+
*
|
|
265
|
+
* // Open browser to authorization URL with redirect_uri set to server.redirectUri
|
|
266
|
+
*
|
|
267
|
+
* const result = await server.waitForCallback();
|
|
268
|
+
* console.log('Got code:', result.code);
|
|
269
|
+
*
|
|
270
|
+
* await server.shutdown();
|
|
271
|
+
* ```
|
|
272
|
+
*/
|
|
273
|
+
declare function startCallbackServer(options?: CallbackServerOptions): Promise<CallbackServer>;
|
|
274
|
+
/**
|
|
275
|
+
* Find an available port
|
|
276
|
+
*/
|
|
277
|
+
declare function findAvailablePort(preferredPort?: number): Promise<number>;
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* OAuth Metadata Discovery (RFC 8414)
|
|
281
|
+
*
|
|
282
|
+
* Discovers OAuth 2.0 authorization server metadata from .well-known endpoints.
|
|
283
|
+
* Supports both OAuth 2.0 and OpenID Connect discovery.
|
|
284
|
+
*/
|
|
285
|
+
/**
|
|
286
|
+
* OAuth 2.0 Authorization Server Metadata
|
|
287
|
+
* https://tools.ietf.org/html/rfc8414
|
|
288
|
+
*/
|
|
289
|
+
interface OAuthMetadata {
|
|
290
|
+
/** Authorization server's issuer identifier URL */
|
|
291
|
+
issuer: string;
|
|
292
|
+
/** URL of the authorization endpoint */
|
|
293
|
+
authorization_endpoint: string;
|
|
294
|
+
/** URL of the token endpoint */
|
|
295
|
+
token_endpoint: string;
|
|
296
|
+
/** URL of the dynamic client registration endpoint */
|
|
297
|
+
registration_endpoint?: string;
|
|
298
|
+
/** URL of the token revocation endpoint */
|
|
299
|
+
revocation_endpoint?: string;
|
|
300
|
+
/** URL of the token introspection endpoint */
|
|
301
|
+
introspection_endpoint?: string;
|
|
302
|
+
/** URL of the userinfo endpoint (OpenID Connect) */
|
|
303
|
+
userinfo_endpoint?: string;
|
|
304
|
+
/** URL of the JWKS endpoint */
|
|
305
|
+
jwks_uri?: string;
|
|
306
|
+
/** Scopes supported by the authorization server */
|
|
307
|
+
scopes_supported?: string[];
|
|
308
|
+
/** Response types supported */
|
|
309
|
+
response_types_supported?: string[];
|
|
310
|
+
/** Response modes supported */
|
|
311
|
+
response_modes_supported?: string[];
|
|
312
|
+
/** Grant types supported */
|
|
313
|
+
grant_types_supported?: string[];
|
|
314
|
+
/** Token endpoint auth methods supported */
|
|
315
|
+
token_endpoint_auth_methods_supported?: string[];
|
|
316
|
+
/** Code challenge methods supported (PKCE) */
|
|
317
|
+
code_challenge_methods_supported?: string[];
|
|
318
|
+
/** Whether server requires PKCE */
|
|
319
|
+
require_pkce?: boolean;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Discovery options
|
|
323
|
+
*/
|
|
324
|
+
interface DiscoveryOptions {
|
|
325
|
+
/** Request timeout in ms (default: 10000) */
|
|
326
|
+
timeout?: number;
|
|
327
|
+
/** Whether to cache the metadata (default: true) */
|
|
328
|
+
cache?: boolean;
|
|
329
|
+
/** Custom fetch function */
|
|
330
|
+
fetch?: typeof fetch;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Discover OAuth metadata from a server URL
|
|
334
|
+
*
|
|
335
|
+
* Tries the following .well-known endpoints in order:
|
|
336
|
+
* 1. /.well-known/oauth-authorization-server
|
|
337
|
+
* 2. /.well-known/openid-configuration
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```typescript
|
|
341
|
+
* const metadata = await discoverOAuthMetadata('https://auth.example.com');
|
|
342
|
+
* console.log('Auth endpoint:', metadata.authorization_endpoint);
|
|
343
|
+
* console.log('Supports PKCE:', metadata.code_challenge_methods_supported?.includes('S256'));
|
|
344
|
+
* ```
|
|
345
|
+
*/
|
|
346
|
+
declare function discoverOAuthMetadata(serverUrl: string, options?: DiscoveryOptions): Promise<OAuthMetadata>;
|
|
347
|
+
/**
|
|
348
|
+
* Clear cached metadata for a server
|
|
349
|
+
*/
|
|
350
|
+
declare function clearMetadataCache(serverUrl?: string): void;
|
|
351
|
+
/**
|
|
352
|
+
* Check if server supports a specific feature based on metadata
|
|
353
|
+
*/
|
|
354
|
+
declare function serverSupports(metadata: OAuthMetadata, feature: 'pkce' | 'refresh_token' | 'dynamic_registration' | 'revocation'): boolean;
|
|
355
|
+
/**
|
|
356
|
+
* Validate that metadata has required fields
|
|
357
|
+
*/
|
|
358
|
+
declare function validateMetadata(metadata: OAuthMetadata): {
|
|
359
|
+
valid: boolean;
|
|
360
|
+
errors: string[];
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Background Token Refresh Manager
|
|
365
|
+
*
|
|
366
|
+
* Automatically refreshes tokens before they expire, ensuring
|
|
367
|
+
* uninterrupted access without user-visible authentication prompts.
|
|
368
|
+
*/
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Token refresh callback
|
|
372
|
+
*/
|
|
373
|
+
type RefreshCallback = (refreshToken: string) => Promise<OAuthTokens>;
|
|
374
|
+
/**
|
|
375
|
+
* Refresh event types
|
|
376
|
+
*/
|
|
377
|
+
type RefreshEvent = {
|
|
378
|
+
type: 'refresh_started';
|
|
379
|
+
serverUrl: string;
|
|
380
|
+
} | {
|
|
381
|
+
type: 'refresh_success';
|
|
382
|
+
serverUrl: string;
|
|
383
|
+
tokens: OAuthTokens;
|
|
384
|
+
} | {
|
|
385
|
+
type: 'refresh_failed';
|
|
386
|
+
serverUrl: string;
|
|
387
|
+
error: Error;
|
|
388
|
+
} | {
|
|
389
|
+
type: 'token_expired';
|
|
390
|
+
serverUrl: string;
|
|
391
|
+
};
|
|
392
|
+
/**
|
|
393
|
+
* Event listener callback
|
|
394
|
+
*/
|
|
395
|
+
type RefreshEventListener = (event: RefreshEvent) => void;
|
|
396
|
+
/**
|
|
397
|
+
* Refresh manager options
|
|
398
|
+
*/
|
|
399
|
+
interface RefreshManagerOptions {
|
|
400
|
+
/** Token storage backend */
|
|
401
|
+
storage: TokenStorage;
|
|
402
|
+
/** Function to refresh tokens */
|
|
403
|
+
refreshFn: RefreshCallback;
|
|
404
|
+
/** Server URL this manager is for */
|
|
405
|
+
serverUrl: string;
|
|
406
|
+
/** Seconds before expiry to trigger refresh (default: 300 = 5 minutes) */
|
|
407
|
+
refreshBuffer?: number;
|
|
408
|
+
/** Check interval in ms (default: 60000 = 1 minute) */
|
|
409
|
+
checkInterval?: number;
|
|
410
|
+
/** Maximum retry attempts on failure (default: 3) */
|
|
411
|
+
maxRetries?: number;
|
|
412
|
+
/** Retry delay in ms (default: 5000) */
|
|
413
|
+
retryDelay?: number;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Background Token Refresh Manager
|
|
417
|
+
*
|
|
418
|
+
* Monitors token expiry and automatically refreshes before expiration.
|
|
419
|
+
*
|
|
420
|
+
* @example
|
|
421
|
+
* ```typescript
|
|
422
|
+
* const manager = new RefreshManager({
|
|
423
|
+
* storage,
|
|
424
|
+
* serverUrl: 'https://mcp.example.com',
|
|
425
|
+
* refreshFn: async (refreshToken) => {
|
|
426
|
+
* // Call token endpoint with refresh_token grant
|
|
427
|
+
* return await exchangeRefreshToken(refreshToken);
|
|
428
|
+
* },
|
|
429
|
+
* });
|
|
430
|
+
*
|
|
431
|
+
* manager.on((event) => {
|
|
432
|
+
* if (event.type === 'refresh_failed') {
|
|
433
|
+
* console.error('Token refresh failed:', event.error);
|
|
434
|
+
* }
|
|
435
|
+
* });
|
|
436
|
+
*
|
|
437
|
+
* manager.start();
|
|
438
|
+
*
|
|
439
|
+
* // Later...
|
|
440
|
+
* manager.stop();
|
|
441
|
+
* ```
|
|
442
|
+
*/
|
|
443
|
+
declare class RefreshManager {
|
|
444
|
+
private storage;
|
|
445
|
+
private refreshFn;
|
|
446
|
+
private serverUrl;
|
|
447
|
+
private refreshBuffer;
|
|
448
|
+
private checkInterval;
|
|
449
|
+
private maxRetries;
|
|
450
|
+
private retryDelay;
|
|
451
|
+
private intervalId?;
|
|
452
|
+
private pendingRefresh?;
|
|
453
|
+
private retryCount;
|
|
454
|
+
private listeners;
|
|
455
|
+
private isRunning;
|
|
456
|
+
constructor(options: RefreshManagerOptions);
|
|
457
|
+
/**
|
|
458
|
+
* Start background refresh monitoring
|
|
459
|
+
*/
|
|
460
|
+
start(): void;
|
|
461
|
+
/**
|
|
462
|
+
* Stop background refresh monitoring
|
|
463
|
+
*/
|
|
464
|
+
stop(): void;
|
|
465
|
+
/**
|
|
466
|
+
* Register event listener
|
|
467
|
+
*/
|
|
468
|
+
on(listener: RefreshEventListener): () => void;
|
|
469
|
+
/**
|
|
470
|
+
* Emit event to all listeners
|
|
471
|
+
*/
|
|
472
|
+
private emit;
|
|
473
|
+
/**
|
|
474
|
+
* Check token and refresh if needed
|
|
475
|
+
*/
|
|
476
|
+
private checkAndRefresh;
|
|
477
|
+
/**
|
|
478
|
+
* Perform token refresh with retry logic
|
|
479
|
+
*/
|
|
480
|
+
private performRefresh;
|
|
481
|
+
/**
|
|
482
|
+
* Actually perform the refresh
|
|
483
|
+
*/
|
|
484
|
+
private doRefresh;
|
|
485
|
+
/**
|
|
486
|
+
* Force an immediate refresh
|
|
487
|
+
*/
|
|
488
|
+
forceRefresh(): Promise<OAuthTokens>;
|
|
489
|
+
/**
|
|
490
|
+
* Get current running state
|
|
491
|
+
*/
|
|
492
|
+
get running(): boolean;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Create a simple refresh manager for an OAuth client
|
|
496
|
+
*/
|
|
497
|
+
declare function createRefreshManager(storage: TokenStorage, serverUrl: string, tokenEndpoint: string, clientId: string, clientSecret?: string): RefreshManager;
|
|
498
|
+
|
|
499
|
+
export { type CallbackError, type CallbackResult, type CallbackServer, type CallbackServerOptions, type DiscoveryOptions, OAuthClient, type OAuthClientOptions, type OAuthMetadata, type PKCEPair, type RefreshCallback, type RefreshEvent, type RefreshEventListener, RefreshManager, type RefreshManagerOptions, clearMetadataCache, createRefreshManager, discoverOAuthMetadata, findAvailablePort, generateCodeChallenge, generateCodeVerifier, generatePKCE, isValidCodeVerifier, serverSupports, startCallbackServer, validateMetadata, verifyPKCE };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for @leanmcp/auth
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Options for the Authenticated decorator
|
|
6
|
+
*/
|
|
7
|
+
interface AuthenticatedOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Whether to fetch and attach user information to authUser variable
|
|
10
|
+
* @default true
|
|
11
|
+
*/
|
|
12
|
+
getUser?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Project ID for fetching user environment variables.
|
|
15
|
+
* Required when @RequireEnv is used on the method or class.
|
|
16
|
+
* Used to scope user secrets to a specific project.
|
|
17
|
+
*/
|
|
18
|
+
projectId?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Global authUser type declaration
|
|
23
|
+
* This makes authUser available in @Authenticated methods without explicit declaration
|
|
24
|
+
*/
|
|
25
|
+
declare global {
|
|
26
|
+
/**
|
|
27
|
+
* Authenticated user object automatically available in @Authenticated methods
|
|
28
|
+
*
|
|
29
|
+
* Implemented as a getter that reads from AsyncLocalStorage for concurrency safety.
|
|
30
|
+
* Each request has its own isolated context - 100% safe for concurrent requests.
|
|
31
|
+
*/
|
|
32
|
+
const authUser: any;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get the current authenticated user from the async context
|
|
36
|
+
* This is safe for concurrent requests as each request has its own context
|
|
37
|
+
*/
|
|
38
|
+
declare function getAuthUser(): any;
|
|
39
|
+
/**
|
|
40
|
+
* Authentication error class for better error handling
|
|
41
|
+
*/
|
|
42
|
+
declare class AuthenticationError extends Error {
|
|
43
|
+
code: string;
|
|
44
|
+
constructor(message: string, code: string);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Decorator to protect MCP tools, prompts, resources, or entire services with authentication
|
|
48
|
+
*
|
|
49
|
+
* CONCURRENCY SAFE: Uses AsyncLocalStorage to ensure each request has its own isolated
|
|
50
|
+
* authUser context, preventing race conditions in high-concurrency scenarios.
|
|
51
|
+
*
|
|
52
|
+
* Usage:
|
|
53
|
+
*
|
|
54
|
+
* 1. Protect individual methods with automatic user info:
|
|
55
|
+
* ```typescript
|
|
56
|
+
* @Tool({ description: 'Analyze sentiment' })
|
|
57
|
+
* @Authenticated(authProvider, { getUser: true })
|
|
58
|
+
* async analyzeSentiment(args: AnalyzeSentimentInput): Promise<AnalyzeSentimentOutput> {
|
|
59
|
+
* // authUser is automatically available in method scope
|
|
60
|
+
* console.log('User:', authUser);
|
|
61
|
+
* console.log('User ID:', authUser.sub);
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* 2. Protect without fetching user info:
|
|
66
|
+
* ```typescript
|
|
67
|
+
* @Tool({ description: 'Public tool' })
|
|
68
|
+
* @Authenticated(authProvider, { getUser: false })
|
|
69
|
+
* async publicTool(args: PublicToolInput): Promise<PublicToolOutput> {
|
|
70
|
+
* // Only verifies token, doesn't fetch user info
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* 3. Protect entire service (all tools/prompts/resources):
|
|
75
|
+
* ```typescript
|
|
76
|
+
* @Authenticated(authProvider)
|
|
77
|
+
* export class SentimentAnalysisService {
|
|
78
|
+
* @Tool({ description: 'Analyze sentiment' })
|
|
79
|
+
* async analyzeSentiment(args: AnalyzeSentimentInput) {
|
|
80
|
+
* // All methods in this service require authentication
|
|
81
|
+
* // authUser is automatically available in all methods
|
|
82
|
+
* console.log('User:', authUser);
|
|
83
|
+
* }
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* The decorator expects authentication token in the MCP request _meta field:
|
|
88
|
+
* ```json
|
|
89
|
+
* {
|
|
90
|
+
* "method": "tools/call",
|
|
91
|
+
* "params": {
|
|
92
|
+
* "name": "toolName",
|
|
93
|
+
* "arguments": { ...businessData },
|
|
94
|
+
* "_meta": {
|
|
95
|
+
* "authorization": {
|
|
96
|
+
* "type": "bearer",
|
|
97
|
+
* "token": "your-jwt-token"
|
|
98
|
+
* }
|
|
99
|
+
* }
|
|
100
|
+
* }
|
|
101
|
+
* }
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* @param authProvider - Instance of AuthProviderBase to use for token verification
|
|
105
|
+
* @param options - Optional configuration for authentication behavior
|
|
106
|
+
*/
|
|
107
|
+
declare function Authenticated(authProvider: AuthProviderBase, options?: AuthenticatedOptions): (target: any, propertyKey?: string | symbol, descriptor?: PropertyDescriptor) => any;
|
|
108
|
+
/**
|
|
109
|
+
* Check if a method or class requires authentication
|
|
110
|
+
*/
|
|
111
|
+
declare function isAuthenticationRequired(target: any): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Get the auth provider for a method or class
|
|
114
|
+
*/
|
|
115
|
+
declare function getAuthProvider(target: any): AuthProviderBase | undefined;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @leanmcp/auth - Authentication Module
|
|
119
|
+
*
|
|
120
|
+
* This module provides a base class for implementing authentication providers for MCP tools.
|
|
121
|
+
* Extend AuthProviderBase to integrate with different auth providers (Clerk, Stripe, Firebase, etc.)
|
|
122
|
+
*/
|
|
123
|
+
/**
|
|
124
|
+
* Base class for authentication providers
|
|
125
|
+
* Extend this class to implement integrations with different auth providers
|
|
126
|
+
*/
|
|
127
|
+
declare abstract class AuthProviderBase {
|
|
128
|
+
/**
|
|
129
|
+
* Initialize the auth provider with configuration
|
|
130
|
+
*/
|
|
131
|
+
abstract init(config?: any): Promise<void>;
|
|
132
|
+
/**
|
|
133
|
+
* Refresh an authentication token
|
|
134
|
+
*/
|
|
135
|
+
abstract refreshToken(refreshToken: string, username?: string): Promise<any>;
|
|
136
|
+
/**
|
|
137
|
+
* Verify if a token is valid
|
|
138
|
+
*/
|
|
139
|
+
abstract verifyToken(token: string): Promise<boolean>;
|
|
140
|
+
/**
|
|
141
|
+
* Get user information from a token
|
|
142
|
+
*/
|
|
143
|
+
abstract getUser(token: string): Promise<any>;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Unified AuthProvider class that dynamically selects the appropriate auth provider
|
|
147
|
+
* based on the provider parameter
|
|
148
|
+
*/
|
|
149
|
+
declare class AuthProvider extends AuthProviderBase {
|
|
150
|
+
private providerInstance;
|
|
151
|
+
private providerType;
|
|
152
|
+
private config;
|
|
153
|
+
constructor(provider: string, config?: any);
|
|
154
|
+
/**
|
|
155
|
+
* Initialize the selected auth provider
|
|
156
|
+
*/
|
|
157
|
+
init(config?: any): Promise<void>;
|
|
158
|
+
/**
|
|
159
|
+
* Refresh an authentication token
|
|
160
|
+
*/
|
|
161
|
+
refreshToken(refreshToken: string, username?: string): Promise<any>;
|
|
162
|
+
/**
|
|
163
|
+
* Verify if a token is valid
|
|
164
|
+
*/
|
|
165
|
+
verifyToken(token: string): Promise<boolean>;
|
|
166
|
+
/**
|
|
167
|
+
* Get user information from a token
|
|
168
|
+
*/
|
|
169
|
+
getUser(token: string): Promise<any>;
|
|
170
|
+
/**
|
|
171
|
+
* Get user secrets for a project (LeanMCP provider only)
|
|
172
|
+
* Other providers will return empty object
|
|
173
|
+
*/
|
|
174
|
+
getUserSecrets(token: string, projectId: string): Promise<Record<string, string>>;
|
|
175
|
+
/**
|
|
176
|
+
* Get the provider type
|
|
177
|
+
*/
|
|
178
|
+
getProviderType(): string;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export { AuthProvider, AuthProviderBase, Authenticated, type AuthenticatedOptions, AuthenticationError, getAuthProvider, getAuthUser, isAuthenticationRequired };
|