@ni-c/mcp-hub 0.9.2 → 0.11.0

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.
Files changed (96) hide show
  1. package/CHANGELOG.md +619 -0
  2. package/README.md +189 -64
  3. package/dist/admin.js +232 -8
  4. package/dist/admin.js.map +1 -1
  5. package/dist/auth/address.js +89 -0
  6. package/dist/auth/address.js.map +1 -0
  7. package/dist/auth/api-tokens.js +27 -0
  8. package/dist/auth/api-tokens.js.map +1 -0
  9. package/dist/auth/cimd.js +367 -0
  10. package/dist/auth/cimd.js.map +1 -0
  11. package/dist/auth/consent-page.js +4 -7
  12. package/dist/auth/consent-page.js.map +1 -1
  13. package/dist/auth/headers.js +22 -1
  14. package/dist/auth/headers.js.map +1 -1
  15. package/dist/auth/login-page.js +4 -7
  16. package/dist/auth/login-page.js.map +1 -1
  17. package/dist/auth/oidc/adapter.js +135 -0
  18. package/dist/auth/oidc/adapter.js.map +1 -0
  19. package/dist/auth/oidc/interactions.js +187 -0
  20. package/dist/auth/oidc/interactions.js.map +1 -0
  21. package/dist/auth/oidc/mount.js +144 -0
  22. package/dist/auth/oidc/mount.js.map +1 -0
  23. package/dist/auth/oidc/provider.js +440 -0
  24. package/dist/auth/oidc/provider.js.map +1 -0
  25. package/dist/auth/oidc/quirks.js +234 -0
  26. package/dist/auth/oidc/quirks.js.map +1 -0
  27. package/dist/auth/oidc/verifier.js +121 -0
  28. package/dist/auth/oidc/verifier.js.map +1 -0
  29. package/dist/auth/page.js +22 -0
  30. package/dist/auth/page.js.map +1 -1
  31. package/dist/auth/pinned-fetch.js +129 -0
  32. package/dist/auth/pinned-fetch.js.map +1 -0
  33. package/dist/auth/protected-resource.js +41 -0
  34. package/dist/auth/protected-resource.js.map +1 -0
  35. package/dist/auth/rate-limit.js +156 -0
  36. package/dist/auth/rate-limit.js.map +1 -0
  37. package/dist/auth/redirect-uri.js +90 -0
  38. package/dist/auth/redirect-uri.js.map +1 -0
  39. package/dist/auth/registration.js +146 -0
  40. package/dist/auth/registration.js.map +1 -0
  41. package/dist/auth/session.js +43 -0
  42. package/dist/auth/session.js.map +1 -0
  43. package/dist/auth/signed-token.js +49 -0
  44. package/dist/auth/signed-token.js.map +1 -0
  45. package/dist/auth/store.js +516 -5
  46. package/dist/auth/store.js.map +1 -1
  47. package/dist/auth/text.js +51 -0
  48. package/dist/auth/text.js.map +1 -0
  49. package/dist/config.js +184 -5
  50. package/dist/config.js.map +1 -1
  51. package/dist/docker-proxy/policy.js +1 -0
  52. package/dist/docker-proxy/policy.js.map +1 -1
  53. package/dist/docker-proxy/server.js +1 -0
  54. package/dist/docker-proxy/server.js.map +1 -1
  55. package/dist/elicitation.js +0 -0
  56. package/dist/elicitation.js.map +1 -0
  57. package/dist/forward.js +0 -0
  58. package/dist/forward.js.map +1 -0
  59. package/dist/health.js +22 -3
  60. package/dist/health.js.map +1 -1
  61. package/dist/hub.js +337 -29
  62. package/dist/hub.js.map +1 -1
  63. package/dist/index.js +218 -23
  64. package/dist/index.js.map +1 -1
  65. package/dist/limits.js +13 -1
  66. package/dist/limits.js.map +1 -1
  67. package/dist/mcp-limits.js +14 -2
  68. package/dist/mcp-limits.js.map +1 -1
  69. package/dist/proxy.js +262 -34
  70. package/dist/proxy.js.map +1 -1
  71. package/dist/stdio.js +97 -7
  72. package/dist/stdio.js.map +1 -1
  73. package/dist/subscriptions.js +236 -0
  74. package/dist/subscriptions.js.map +1 -0
  75. package/dist/supervisor.js +472 -28
  76. package/dist/supervisor.js.map +1 -1
  77. package/dist/timings.js +61 -0
  78. package/dist/timings.js.map +1 -0
  79. package/dist/tool-filter.js +59 -0
  80. package/dist/tool-filter.js.map +1 -0
  81. package/dist/transports/docker.js.map +1 -1
  82. package/dist/transports/stream.js +33 -20
  83. package/dist/transports/stream.js.map +1 -1
  84. package/dist/upstream/auth.js +435 -0
  85. package/dist/upstream/auth.js.map +1 -0
  86. package/dist/upstream/login.js +94 -0
  87. package/dist/upstream/login.js.map +1 -0
  88. package/dist/upstream/provider.js +286 -0
  89. package/dist/upstream/provider.js.map +1 -0
  90. package/dist/upstream/routes.js +97 -0
  91. package/dist/upstream/routes.js.map +1 -0
  92. package/package.json +23 -7
  93. package/dist/auth/provider.js +0 -380
  94. package/dist/auth/provider.js.map +0 -1
  95. package/dist/auth/routes.js +0 -223
  96. package/dist/auth/routes.js.map +0 -1
@@ -1,380 +0,0 @@
1
- import crypto from 'node:crypto';
2
- import { SignJWT, jwtVerify } from 'jose';
3
- import { InvalidGrantError, InvalidTargetError, InvalidTokenError } from '@modelcontextprotocol/sdk/server/auth/errors.js';
4
- import { redirectUriMatches } from '@modelcontextprotocol/sdk/server/auth/handlers/authorize.js';
5
- import { renderLoginPage } from './login-page.js';
6
- import { renderConsentPage } from './consent-page.js';
7
- import { allowFormActionTo } from './headers.js';
8
- const ACCESS_TOKEN_TTL_S = 15 * 60;
9
- const REFRESH_TOKEN_TTL_S = 30 * 24 * 3600;
10
- const CODE_TTL_MS = 10 * 60_000;
11
- export const SESSION_TTL_MS = 30 * 60_000;
12
- export const SESSION_COOKIE = 'mcp_hub_session';
13
- /**
14
- * The `__Host-` prefix pins the cookie to this exact origin, so no neighbouring
15
- * subdomain can plant one. It requires Secure, which rules it out over plain
16
- * http (local development and the test suite).
17
- */
18
- export function sessionCookieName(externalUrl) {
19
- return new URL(externalUrl).protocol === 'https:' ? `__Host-${SESSION_COOKIE}` : SESSION_COOKIE;
20
- }
21
- function sign(value, secret) {
22
- return crypto.createHmac('sha256', secret).update(value).digest('base64url');
23
- }
24
- /** Distinguishes admin-minted API tokens from interactive OAuth tokens. */
25
- export const API_TOKEN_SUBJECT = 'mcp-hub-token';
26
- /**
27
- * Mint a long-lived, resource-bound API token for clients that cannot do
28
- * OAuth (OpenAI Responses API, xAI API, Gemini API, plain-header clients).
29
- * The JWT is returned exactly once; only its record (jti) is persisted, which
30
- * is what `tokens list` shows and `tokens revoke` deletes.
31
- */
32
- export async function mintApiToken(store, externalUrl, resource, days, label) {
33
- const id = crypto.randomBytes(8).toString('base64url');
34
- const now = Math.floor(Date.now() / 1000);
35
- const expiresAt = now + days * 86_400;
36
- const token = await new SignJWT({})
37
- .setProtectedHeader({ alg: 'EdDSA' })
38
- .setIssuer(new URL(externalUrl).href)
39
- .setAudience(resource.href)
40
- .setSubject(API_TOKEN_SUBJECT)
41
- .setIssuedAt(now)
42
- .setExpirationTime(expiresAt)
43
- .setJti(id)
44
- .sign(store.privateKey);
45
- store.saveApiToken(id, { label, resource: resource.href, createdAt: now, expiresAt });
46
- return { id, token, expiresAt };
47
- }
48
- export class HubOAuthProvider {
49
- store;
50
- externalUrl;
51
- options;
52
- /** Short-lived authorization codes; in-memory on purpose (10 min lifetime). */
53
- codes = new Map();
54
- sessionCookieName;
55
- constructor(store, externalUrl, options = {}) {
56
- this.store = store;
57
- this.externalUrl = externalUrl;
58
- this.options = options;
59
- this.sessionCookieName = sessionCookieName(externalUrl);
60
- }
61
- get clientsStore() {
62
- const store = this.store;
63
- return {
64
- getClient: clientId => store.getClient(clientId),
65
- registerClient: client => {
66
- const isPublic = client.token_endpoint_auth_method === 'none';
67
- const stored = {
68
- ...client,
69
- client_id: crypto.randomBytes(16).toString('base64url'),
70
- client_id_issued_at: Math.floor(Date.now() / 1000),
71
- // Secrets never expire: ChatGPT registers once per connector and
72
- // never re-registers, so an expiring secret bricks the connector
73
- // when it runs out (the SDK default is 30 days).
74
- client_secret_expires_at: 0
75
- };
76
- // A stored secret makes the SDK demand it on every token request, so a
77
- // public client must be persisted without one — but ChatGPT expects a
78
- // client_secret in the registration response even for "none" and
79
- // refuses its own registration otherwise. Hand it one in the response
80
- // only; token requests from public clients ignore it.
81
- if (isPublic)
82
- delete stored.client_secret;
83
- store.saveClient(stored);
84
- console.log(`mcp-hub: registered OAuth client ${stored.client_id} (${stored.client_name ?? 'unnamed'})`);
85
- return isPublic ? { ...stored, client_secret: crypto.randomBytes(32).toString('hex'), client_secret_expires_at: 0 } : stored;
86
- }
87
- };
88
- }
89
- // --- Authorization endpoint ---------------------------------------------
90
- /**
91
- * A live session alone must not be enough to hand out a code: the cookie
92
- * rides along on cross-site top-level navigations, so any page could walk a
93
- * logged-in user through /authorize with a client it registered itself and
94
- * collect the code. Only clients the user confirmed once are silent; for
95
- * those the code can only ever land on their own registered redirect_uri.
96
- *
97
- * The SDK re-sends on `res` if this method throws, so nothing may throw
98
- * after the response has gone out.
99
- */
100
- async authorize(client, params, res) {
101
- const resource = this.resolveResource(params.resource);
102
- const session = this.readSessionCookie(res.req.headers.cookie);
103
- if (session && this.isApproved(client, params.redirectUri)) {
104
- this.redirectWithCode(client, { ...params, resource }, res);
105
- return;
106
- }
107
- const request = this.signPending(client, { ...params, resource });
108
- const page = session
109
- ? renderConsentPage(request, this.csrfToken(session), params.redirectUri, client.client_name, resource?.href)
110
- : renderLoginPage(request, params.redirectUri, client.client_name, undefined, resource?.href);
111
- // Submitting either form ends in a redirect to this client's redirect_uri,
112
- // which the SDK has already matched against its registration.
113
- allowFormActionTo(res, params.redirectUri);
114
- res.status(200).type('html').send(page);
115
- }
116
- /** Everything the login/consent form has to carry across, signed so it
117
- * cannot be tampered with while it sits in the browser. */
118
- signPending(client, params) {
119
- const resource = this.resolveResource(params.resource);
120
- const pending = {
121
- clientId: client.client_id,
122
- redirectUri: params.redirectUri,
123
- codeChallenge: params.codeChallenge,
124
- state: params.state,
125
- scopes: params.scopes ?? [],
126
- exp: Date.now() + CODE_TTL_MS,
127
- resource: resource?.href
128
- };
129
- const payload = Buffer.from(JSON.stringify(pending)).toString('base64url');
130
- return `${payload}.${sign(payload, this.store.cookieSecret)}`;
131
- }
132
- isApproved(client, redirectUri) {
133
- const approval = this.store.getApproval(client.client_id);
134
- // Same matching the SDK applies at registration, so a loopback client that
135
- // picks a fresh port every run stays approved.
136
- return approval?.redirectUris.some(uri => redirectUriMatches(redirectUri, uri)) ?? false;
137
- }
138
- approve(client, redirectUri) {
139
- this.store.saveApproval(client.client_id, redirectUri, client.client_name);
140
- console.log(`mcp-hub: approved OAuth client ${client.client_id} (${client.client_name ?? 'unnamed'}) for ${redirectUri}`);
141
- }
142
- decodePendingAuthorization(token) {
143
- const [payload, signature] = token.split('.');
144
- if (!payload || !signature)
145
- return undefined;
146
- const expected = sign(payload, this.store.cookieSecret);
147
- if (signature.length !== expected.length || !crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)))
148
- return undefined;
149
- const pending = JSON.parse(Buffer.from(payload, 'base64url').toString());
150
- if (pending.exp < Date.now())
151
- return undefined;
152
- return pending;
153
- }
154
- redirectWithCode(client, params, res) {
155
- const resource = typeof params.resource === 'string' ? params.resource : this.resolveResource(params.resource)?.href;
156
- const code = crypto.randomBytes(32).toString('base64url');
157
- this.sweepExpiredCodes();
158
- this.codes.set(code, {
159
- clientId: client.client_id,
160
- codeChallenge: params.codeChallenge,
161
- redirectUri: params.redirectUri,
162
- scopes: params.scopes ?? [],
163
- expiresAt: Date.now() + CODE_TTL_MS,
164
- resource
165
- });
166
- const target = new URL(params.redirectUri);
167
- target.searchParams.set('code', code);
168
- if (params.state !== undefined)
169
- target.searchParams.set('state', params.state);
170
- res.redirect(target.toString());
171
- }
172
- /** RFC 6749 §4.1.2.1 — tell the client it was turned down instead of
173
- * leaving it to time out. */
174
- redirectWithError(redirectUri, state, error, res) {
175
- const target = new URL(redirectUri);
176
- target.searchParams.set('error', error);
177
- if (state !== undefined)
178
- target.searchParams.set('state', state);
179
- res.redirect(target.toString());
180
- }
181
- /** Codes are otherwise only dropped on redemption, so unredeemed ones from
182
- * anyone who can register a client would accumulate for the process' life. */
183
- sweepExpiredCodes() {
184
- const now = Date.now();
185
- for (const [code, pending] of this.codes) {
186
- if (pending.expiresAt < now)
187
- this.codes.delete(code);
188
- }
189
- }
190
- // --- Session cookie ------------------------------------------------------
191
- createSessionCookie() {
192
- const expires = String(Date.now() + SESSION_TTL_MS);
193
- return `${expires}.${sign(expires, this.store.cookieSecret)}`;
194
- }
195
- /** The verified cookie value, which doubles as the handle the consent
196
- * form's CSRF token is bound to. */
197
- readSessionCookie(cookieHeader) {
198
- const match = cookieHeader?.match(new RegExp(`(?:^|;\\s*)${this.sessionCookieName}=([^;]+)`));
199
- if (!match)
200
- return undefined;
201
- const value = decodeURIComponent(match[1]);
202
- const [expires, signature] = value.split('.');
203
- if (!expires || !signature)
204
- return undefined;
205
- const expected = sign(expires, this.store.cookieSecret);
206
- if (signature.length !== expected.length || !crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)))
207
- return undefined;
208
- return Number(expires) > Date.now() ? value : undefined;
209
- }
210
- hasValidSession(cookieHeader) {
211
- return this.readSessionCookie(cookieHeader) !== undefined;
212
- }
213
- csrfToken(sessionValue) {
214
- return sign(`csrf:${sessionValue}`, this.store.cookieSecret);
215
- }
216
- verifyCsrfToken(sessionValue, token) {
217
- if (typeof token !== 'string')
218
- return false;
219
- const expected = this.csrfToken(sessionValue);
220
- return token.length === expected.length && crypto.timingSafeEqual(Buffer.from(token), Buffer.from(expected));
221
- }
222
- // --- Token endpoint ------------------------------------------------------
223
- async challengeForAuthorizationCode(_client, authorizationCode) {
224
- const pending = this.codes.get(authorizationCode);
225
- if (!pending || pending.expiresAt < Date.now())
226
- throw new InvalidGrantError('Invalid or expired authorization code');
227
- return pending.codeChallenge;
228
- }
229
- async exchangeAuthorizationCode(client, authorizationCode, _codeVerifier, redirectUri, resource) {
230
- const pending = this.codes.get(authorizationCode);
231
- if (!pending || pending.expiresAt < Date.now() || pending.clientId !== client.client_id) {
232
- throw new InvalidGrantError('Invalid or expired authorization code');
233
- }
234
- if (redirectUri !== undefined && redirectUri !== pending.redirectUri) {
235
- throw new InvalidGrantError('redirect_uri does not match the authorization request');
236
- }
237
- const requestedResource = resource ? this.resolveResource(resource) : undefined;
238
- if (resource && requestedResource?.href !== pending.resource) {
239
- throw new InvalidGrantError('resource does not match the authorization request');
240
- }
241
- this.codes.delete(authorizationCode); // single use
242
- return this.issueTokens(client.client_id, pending.scopes, undefined, pending.resource);
243
- }
244
- async exchangeRefreshToken(client, refreshToken, scopes, resource) {
245
- const record = this.store.getRefreshToken(refreshToken);
246
- if (!record || record.clientId !== client.client_id) {
247
- // Seeing a token that was already rotated away means the chain leaked:
248
- // the legitimate holder and someone else both have one. Drop them all.
249
- const consumed = this.store.wasConsumed(refreshToken);
250
- if (consumed) {
251
- const revoked = this.store.revokeFamily(consumed.familyId);
252
- console.warn(`mcp-hub: refresh token replay from client ${client.client_id}, revoked ${revoked} token(s)`);
253
- }
254
- throw new InvalidGrantError('Invalid refresh token');
255
- }
256
- if (scopes && !scopes.every(scope => record.scopes.includes(scope))) {
257
- throw new InvalidGrantError('Requested scopes exceed the original grant');
258
- }
259
- const requestedResource = resource ? this.resolveResource(resource) : undefined;
260
- if (resource && !requestedResource)
261
- throw new InvalidTargetError('Unknown or invalid resource');
262
- if (record.resource && requestedResource && record.resource !== requestedResource.href) {
263
- throw new InvalidGrantError('resource does not match the original grant');
264
- }
265
- const tokenResource = requestedResource?.href ?? record.resource;
266
- if (this.options.requireResource && !tokenResource)
267
- throw new InvalidTargetError('A resource indicator is required');
268
- // Tokens issued before families existed adopt one on their first rotation.
269
- const familyId = record.familyId ?? crypto.randomBytes(16).toString('base64url');
270
- this.store.consumeRefreshToken(refreshToken, familyId, record.expiresAt);
271
- return this.issueTokens(client.client_id, scopes ?? record.scopes, familyId, tokenResource);
272
- }
273
- async issueTokens(clientId, scopes, familyId = crypto.randomBytes(16).toString('base64url'), resource) {
274
- const issuedMs = Date.now();
275
- const accessToken = await new SignJWT({ client_id: clientId, scope: scopes.join(' '), issued_ms: issuedMs })
276
- .setProtectedHeader({ alg: 'EdDSA' })
277
- .setIssuer(this.externalUrl)
278
- .setAudience(resource ?? this.externalUrl)
279
- .setSubject('mcp-hub-user')
280
- .setIssuedAt()
281
- .setExpirationTime(`${ACCESS_TOKEN_TTL_S}s`)
282
- .setJti(crypto.randomBytes(8).toString('base64url'))
283
- .sign(this.store.privateKey);
284
- const refreshToken = `rt_${crypto.randomBytes(32).toString('base64url')}`;
285
- this.store.saveRefreshToken(refreshToken, {
286
- clientId,
287
- scopes,
288
- expiresAt: Math.floor(Date.now() / 1000) + REFRESH_TOKEN_TTL_S,
289
- familyId,
290
- resource
291
- });
292
- return {
293
- access_token: accessToken,
294
- token_type: 'Bearer',
295
- expires_in: ACCESS_TOKEN_TTL_S,
296
- refresh_token: refreshToken,
297
- scope: scopes.join(' ') || undefined
298
- };
299
- }
300
- async verifyAccessToken(token) {
301
- let payload;
302
- try {
303
- ({ payload } = await jwtVerify(token, this.store.publicKey, {
304
- issuer: this.externalUrl,
305
- algorithms: ['EdDSA']
306
- }));
307
- }
308
- catch {
309
- throw new InvalidTokenError('Invalid or expired access token');
310
- }
311
- // Admin-minted API token: same signature and audience rules as an OAuth
312
- // access token, but revocation lives in its state record — a jti whose
313
- // record is gone (revoked or expired) is refused even though the JWT
314
- // itself still verifies.
315
- if (payload.sub === API_TOKEN_SUBJECT) {
316
- if (typeof payload.jti !== 'string' || !this.store.getApiToken(payload.jti)) {
317
- throw new InvalidTokenError('Access token has been revoked');
318
- }
319
- const audience = typeof payload.aud === 'string' ? payload.aud : undefined;
320
- const resource = audience ? this.resolveResourceStrict(audience) : undefined;
321
- if (!resource)
322
- throw new InvalidTokenError('Invalid token audience');
323
- return { token, clientId: `token:${payload.jti}`, scopes: [], expiresAt: payload.exp, resource };
324
- }
325
- if (payload.sub !== 'mcp-hub-user' || typeof payload.client_id !== 'string') {
326
- throw new InvalidTokenError('Invalid access token claims');
327
- }
328
- const audience = typeof payload.aud === 'string' ? payload.aud : undefined;
329
- const resource = audience && audience !== this.externalUrl ? this.resolveResourceStrict(audience) : undefined;
330
- if (!audience || (audience !== this.externalUrl && !resource))
331
- throw new InvalidTokenError('Invalid token audience');
332
- const issuedMs = typeof payload.issued_ms === 'number' ? payload.issued_ms : (payload.iat ?? 0) * 1000;
333
- const revokedBefore = this.store.getRevokedBefore(payload.client_id);
334
- if (revokedBefore !== undefined && issuedMs <= revokedBefore)
335
- throw new InvalidTokenError('Access token has been revoked');
336
- return {
337
- token,
338
- clientId: payload.client_id,
339
- scopes: typeof payload.scope === 'string' && payload.scope.length > 0 ? payload.scope.split(' ') : [],
340
- expiresAt: payload.exp,
341
- resource
342
- };
343
- }
344
- /** Audience check for already-issued tokens: never falls back to a default. */
345
- resolveResourceStrict(audience) {
346
- let url;
347
- try {
348
- url = new URL(audience);
349
- }
350
- catch {
351
- return undefined;
352
- }
353
- return this.options.resolveResource?.(url);
354
- }
355
- async revokeToken(client, request) {
356
- const record = this.store.getRefreshToken(request.token);
357
- if (record && record.clientId === client.client_id)
358
- this.store.deleteRefreshToken(request.token);
359
- // Individual JWTs are not stored; the offline admin command revokes all
360
- // access and refresh tokens for a client through the revokedBefore marker.
361
- }
362
- resolveResource(resource) {
363
- if (!resource) {
364
- // Real clients omit the RFC 8707 parameter (older Codex logins, Google
365
- // ADK, Gemini Enterprise). DEFAULT_RESOURCE lets the operator route
366
- // those onto one chosen resource instead of turning them away — the
367
- // token is still bound, never global.
368
- if (this.options.defaultResource)
369
- return this.options.defaultResource;
370
- if (this.options.requireResource)
371
- throw new InvalidTargetError('A resource indicator is required');
372
- return undefined;
373
- }
374
- const resolved = this.options.resolveResource?.(resource);
375
- if (!resolved)
376
- throw new InvalidTargetError('Unknown or invalid resource');
377
- return resolved;
378
- }
379
- }
380
- //# sourceMappingURL=provider.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/auth/provider.ts"],"names":[],"mappings":"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"}
@@ -1,223 +0,0 @@
1
- import crypto from 'node:crypto';
2
- import express, { Router } from 'express';
3
- import bcrypt from 'bcryptjs';
4
- import { mcpAuthRouter, createOAuthMetadata } from '@modelcontextprotocol/sdk/server/auth/router.js';
5
- import { SESSION_TTL_MS } from './provider.js';
6
- import { renderLoginPage } from './login-page.js';
7
- import { allowFormActionTo, contentSecurityPolicy } from './headers.js';
8
- const LOGIN_MAX_ATTEMPTS = 10;
9
- const LOGIN_WINDOW_MS = 15 * 60_000;
10
- const LOGIN_MAX_ATTEMPTS_TOTAL = 100;
11
- function earlyRateLimit(windowMs, maxPerIp, maxTotal) {
12
- const byIp = new Map();
13
- let total = { count: 0, resetAt: 0 };
14
- return (req, res, next) => {
15
- const now = Date.now();
16
- if (total.resetAt <= now)
17
- total = { count: 0, resetAt: now + windowMs };
18
- const ip = req.ip ?? 'unknown';
19
- let entry = byIp.get(ip);
20
- if (entry && entry.resetAt <= now) {
21
- byIp.delete(ip);
22
- entry = undefined;
23
- }
24
- // Reject before inserting anything: a flood of distinct rejected IPs must
25
- // not grow the map. Accepted requests bound it at maxTotal per window.
26
- if ((entry?.count ?? 0) >= maxPerIp || total.count >= maxTotal) {
27
- res.set('Retry-After', String(Math.max(1, Math.ceil((Math.min(entry?.resetAt ?? Infinity, total.resetAt) - now) / 1000))));
28
- res.status(429).json({ error: 'too_many_requests', error_description: 'Request rate limit exceeded' });
29
- return;
30
- }
31
- if (!entry) {
32
- if (byIp.size >= maxTotal) {
33
- for (const [candidateIp, candidate] of byIp)
34
- if (candidate.resetAt <= now)
35
- byIp.delete(candidateIp);
36
- }
37
- entry = { count: 0, resetAt: now + windowMs };
38
- byIp.set(ip, entry);
39
- }
40
- entry.count++;
41
- total.count++;
42
- next();
43
- };
44
- }
45
- export class LoginRateLimiter {
46
- attempts = new Map();
47
- total = { count: 0, resetAt: 0 };
48
- isBlocked(ip) {
49
- if (this.total.resetAt > Date.now() && this.total.count >= LOGIN_MAX_ATTEMPTS_TOTAL)
50
- return true;
51
- const entry = this.attempts.get(ip);
52
- if (!entry || entry.resetAt < Date.now())
53
- return false;
54
- return entry.count >= LOGIN_MAX_ATTEMPTS;
55
- }
56
- recordFailure(ip) {
57
- this.sweepExpired(); // entries are otherwise only dropped on a successful login from that exact IP
58
- const now = Date.now();
59
- // Behind a reverse proxy req.ip is the proxy for every request, and a
60
- // spoofable X-Forwarded-For makes the per-IP counter meaningless — this
61
- // caps the total either way.
62
- if (this.total.resetAt < now)
63
- this.total = { count: 1, resetAt: now + LOGIN_WINDOW_MS };
64
- else
65
- this.total.count++;
66
- const entry = this.attempts.get(ip);
67
- if (!entry || entry.resetAt < now) {
68
- this.attempts.set(ip, { count: 1, resetAt: now + LOGIN_WINDOW_MS });
69
- }
70
- else {
71
- entry.count++;
72
- }
73
- }
74
- sweepExpired() {
75
- const now = Date.now();
76
- for (const [ip, entry] of this.attempts) {
77
- if (entry.resetAt < now)
78
- this.attempts.delete(ip);
79
- }
80
- }
81
- reset(ip) {
82
- this.attempts.delete(ip);
83
- this.total = { count: 0, resetAt: 0 };
84
- }
85
- }
86
- export function createAuthRoutes(options) {
87
- const { provider, externalUrl } = options;
88
- if (!options.passwordHash && !options.password) {
89
- throw new Error('Either PASSWORD_HASH (bcrypt) or PASSWORD must be set');
90
- }
91
- const issuerUrl = new URL(externalUrl);
92
- const router = Router();
93
- const rateLimiter = new LoginRateLimiter();
94
- // Keep the password login/consent pages and the OAuth token responses out of
95
- // any shared or browser cache (RFC 6749 §5.1 requires no-store on token
96
- // responses; the login form has no business being cached either). The CSP
97
- // and legacy frame header keep an attacker from clickjacking approval or
98
- // password entry. This application has no legitimate framing use case.
99
- router.use((_req, res, next) => {
100
- res.set('Cache-Control', 'no-store');
101
- res.set('Content-Security-Policy', contentSecurityPolicy());
102
- res.set('X-Frame-Options', 'DENY');
103
- res.set('X-Content-Type-Options', 'nosniff');
104
- res.set('Referrer-Policy', 'no-referrer');
105
- next();
106
- });
107
- // These run before the SDK's JSON/form parsers. The SDK applies its own
108
- // endpoint limits too, but those otherwise happen only after body parsing.
109
- router.use('/register', earlyRateLimit(60 * 60_000, 20, 200));
110
- router.use('/authorize', earlyRateLimit(15 * 60_000, 100, 1_000));
111
- router.use('/token', earlyRateLimit(15 * 60_000, 50, 500));
112
- router.use('/login', earlyRateLimit(15 * 60_000, 100, 500));
113
- router.use('/consent', earlyRateLimit(15 * 60_000, 100, 500));
114
- // Standard AS endpoints: /.well-known/*, /authorize, /token, /register, /revoke
115
- router.use(mcpAuthRouter({ provider, issuerUrl, resourceName: 'mcp-hub' }));
116
- // Path-scoped metadata (RFC 9728 §3.1): clients connected to /<name>/mcp look
117
- // up /.well-known/oauth-protected-resource/<name>/mcp before falling back to
118
- // the root document, and RFC 8414 has an equivalent path-insertion form for
119
- // AS metadata. Serve both for any suffix; one AS covers all resources.
120
- const asMetadata = createOAuthMetadata({ provider, issuerUrl });
121
- router.get('/.well-known/oauth-authorization-server/{*splat}', (_req, res) => {
122
- res.json(asMetadata);
123
- });
124
- // OIDC Discovery alias: some clients (ChatGPT among them) probe
125
- // /.well-known/openid-configuration instead of — or before — the RFC 8414
126
- // path, and the MCP spec requires clients to support both. The RFC 8414
127
- // document is a compatible answer for the fields such clients read.
128
- router.get('/.well-known/openid-configuration', (_req, res) => {
129
- res.json(asMetadata);
130
- });
131
- router.get('/.well-known/openid-configuration/{*splat}', (_req, res) => {
132
- res.json(asMetadata);
133
- });
134
- router.get('/.well-known/oauth-protected-resource/{*splat}', (req, res) => {
135
- const suffix = req.path.replace('/.well-known/oauth-protected-resource', '');
136
- res.json({
137
- resource: issuerUrl.origin + suffix,
138
- authorization_servers: [externalUrl],
139
- bearer_methods_supported: ['header'],
140
- resource_name: 'mcp-hub'
141
- });
142
- });
143
- const checkPassword = (password) => {
144
- if (options.passwordHash)
145
- return bcrypt.compareSync(password, options.passwordHash);
146
- const expected = Buffer.from(options.password);
147
- const given = Buffer.from(password);
148
- return expected.length === given.length && crypto.timingSafeEqual(expected, given);
149
- };
150
- router.post('/login', express.urlencoded({ extended: false }), async (req, res) => {
151
- const ip = req.ip ?? 'unknown';
152
- const { password, request } = req.body;
153
- const pending = typeof request === 'string' ? provider.decodePendingAuthorization(request) : undefined;
154
- if (!pending) {
155
- res.status(400).type('html').send('<p>Authorization request expired. Close this window and connect again.</p>');
156
- return;
157
- }
158
- if (rateLimiter.isBlocked(ip)) {
159
- console.warn(`mcp-hub: login rate limit exceeded from ${ip}`);
160
- res.status(429).type('html').send('<p>Too many attempts. Try again later.</p>');
161
- return;
162
- }
163
- if (typeof password !== 'string' || !checkPassword(password)) {
164
- rateLimiter.recordFailure(ip);
165
- console.warn(`mcp-hub: authentication failure from ${ip}`);
166
- // The retry form has to reach the same redirect as the first attempt.
167
- allowFormActionTo(res, pending.redirectUri);
168
- res.status(401).type('html').send(renderLoginPage(request, pending.redirectUri, undefined, 'Wrong password', pending.resource));
169
- return;
170
- }
171
- rateLimiter.reset(ip);
172
- console.log(`mcp-hub: successful login from ${ip}`);
173
- res.cookie(provider.sessionCookieName, provider.createSessionCookie(), {
174
- httpOnly: true,
175
- secure: issuerUrl.protocol === 'https:',
176
- sameSite: 'lax',
177
- maxAge: SESSION_TTL_MS,
178
- path: '/'
179
- });
180
- const client = await provider.clientsStore.getClient(pending.clientId);
181
- if (!client) {
182
- res.status(400).type('html').send('<p>Unknown client. Close this window and connect again.</p>');
183
- return;
184
- }
185
- provider.approve(client, pending.redirectUri); // typing the password is the consent
186
- provider.redirectWithCode(client, pending, res);
187
- });
188
- // Reached from the consent page when a signed-in user authorizes a client
189
- // for the first time. Everything here has to hold even though the request
190
- // may have been triggered by a page the user did not expect to land on.
191
- router.post('/consent', express.urlencoded({ extended: false }), async (req, res) => {
192
- const { request, csrf, action } = req.body;
193
- const pending = typeof request === 'string' ? provider.decodePendingAuthorization(request) : undefined;
194
- if (!pending) {
195
- res.status(400).type('html').send('<p>Authorization request expired. Close this window and connect again.</p>');
196
- return;
197
- }
198
- const session = provider.readSessionCookie(req.headers.cookie);
199
- if (!session) {
200
- res.status(401).type('html').send('<p>Session expired. Close this window and connect again.</p>');
201
- return;
202
- }
203
- if (!provider.verifyCsrfToken(session, csrf)) {
204
- console.warn(`mcp-hub: consent with an invalid CSRF token from ${req.ip ?? 'unknown'}`);
205
- res.status(403).type('html').send('<p>Invalid request. Close this window and connect again.</p>');
206
- return;
207
- }
208
- if (action !== 'approve') {
209
- console.log(`mcp-hub: authorization denied for client ${pending.clientId}`);
210
- provider.redirectWithError(pending.redirectUri, pending.state, 'access_denied', res);
211
- return;
212
- }
213
- const client = await provider.clientsStore.getClient(pending.clientId);
214
- if (!client) {
215
- res.status(400).type('html').send('<p>Unknown client. Close this window and connect again.</p>');
216
- return;
217
- }
218
- provider.approve(client, pending.redirectUri);
219
- provider.redirectWithCode(client, pending, res);
220
- });
221
- return router;
222
- }
223
- //# sourceMappingURL=routes.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/auth/routes.ts"],"names":[],"mappings":"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"}