fastmcp 4.12.7 → 4.13.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.
package/dist/FastMCP.cjs CHANGED
@@ -24,7 +24,7 @@ var _chunkU36NARZGcjs = require('./chunk-U36NARZG.cjs');
24
24
 
25
25
 
26
26
 
27
- var _chunk6DTYLKSCcjs = require('./chunk-6DTYLKSC.cjs');
27
+ var _chunk5FVNY65Mcjs = require('./chunk-5FVNY65M.cjs');
28
28
 
29
29
 
30
30
 
@@ -49,5 +49,5 @@ var _chunk6DTYLKSCcjs = require('./chunk-6DTYLKSC.cjs');
49
49
 
50
50
 
51
51
 
52
- exports.AuthProvider = _chunk6DTYLKSCcjs.AuthProvider; exports.AzureProvider = _chunk6DTYLKSCcjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkU36NARZGcjs.DiscoveryDocumentCache; exports.FastMCP = _chunkU36NARZGcjs.FastMCP; exports.FastMCPError = _chunkU36NARZGcjs.FastMCPError; exports.FastMCPSession = _chunkU36NARZGcjs.FastMCPSession; exports.GitHubProvider = _chunk6DTYLKSCcjs.GitHubProvider; exports.GoogleProvider = _chunk6DTYLKSCcjs.GoogleProvider; exports.MEDIA_FETCH_TIMEOUT_MS = _chunkU36NARZGcjs.MEDIA_FETCH_TIMEOUT_MS; exports.OAuthProvider = _chunk6DTYLKSCcjs.OAuthProvider; exports.ServerState = _chunkU36NARZGcjs.ServerState; exports.SessionError = _chunkU36NARZGcjs.SessionError; exports.UnexpectedStateError = _chunkU36NARZGcjs.UnexpectedStateError; exports.UserError = _chunkU36NARZGcjs.UserError; exports.audioContent = _chunkU36NARZGcjs.audioContent; exports.getAuthSession = _chunk6DTYLKSCcjs.getAuthSession; exports.imageContent = _chunkU36NARZGcjs.imageContent; exports.jsonSchemaAdapter = _chunkU36NARZGcjs.jsonSchemaAdapter; exports.requireAll = _chunk6DTYLKSCcjs.requireAll; exports.requireAny = _chunk6DTYLKSCcjs.requireAny; exports.requireAuth = _chunk6DTYLKSCcjs.requireAuth; exports.requireRole = _chunk6DTYLKSCcjs.requireRole; exports.requireScopes = _chunk6DTYLKSCcjs.requireScopes;
52
+ exports.AuthProvider = _chunk5FVNY65Mcjs.AuthProvider; exports.AzureProvider = _chunk5FVNY65Mcjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkU36NARZGcjs.DiscoveryDocumentCache; exports.FastMCP = _chunkU36NARZGcjs.FastMCP; exports.FastMCPError = _chunkU36NARZGcjs.FastMCPError; exports.FastMCPSession = _chunkU36NARZGcjs.FastMCPSession; exports.GitHubProvider = _chunk5FVNY65Mcjs.GitHubProvider; exports.GoogleProvider = _chunk5FVNY65Mcjs.GoogleProvider; exports.MEDIA_FETCH_TIMEOUT_MS = _chunkU36NARZGcjs.MEDIA_FETCH_TIMEOUT_MS; exports.OAuthProvider = _chunk5FVNY65Mcjs.OAuthProvider; exports.ServerState = _chunkU36NARZGcjs.ServerState; exports.SessionError = _chunkU36NARZGcjs.SessionError; exports.UnexpectedStateError = _chunkU36NARZGcjs.UnexpectedStateError; exports.UserError = _chunkU36NARZGcjs.UserError; exports.audioContent = _chunkU36NARZGcjs.audioContent; exports.getAuthSession = _chunk5FVNY65Mcjs.getAuthSession; exports.imageContent = _chunkU36NARZGcjs.imageContent; exports.jsonSchemaAdapter = _chunkU36NARZGcjs.jsonSchemaAdapter; exports.requireAll = _chunk5FVNY65Mcjs.requireAll; exports.requireAny = _chunk5FVNY65Mcjs.requireAny; exports.requireAuth = _chunk5FVNY65Mcjs.requireAuth; exports.requireRole = _chunk5FVNY65Mcjs.requireRole; exports.requireScopes = _chunk5FVNY65Mcjs.requireScopes;
53
53
  //# sourceMappingURL=FastMCP.cjs.map
@@ -12,8 +12,8 @@ import { CorsOptions } from 'mcp-proxy';
12
12
  export { CorsOptions } from 'mcp-proxy';
13
13
  import { StrictEventEmitter } from 'strict-event-emitter-types';
14
14
  import { z } from 'zod';
15
- import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-B_OJFNC0.cjs';
16
- export { j as AuthProviderConfig, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, d as OAuthProvider, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from './OAuthProvider-B_OJFNC0.cjs';
15
+ import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-Bvt5a7yr.cjs';
16
+ export { j as AuthProviderConfig, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, d as OAuthProvider, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from './OAuthProvider-Bvt5a7yr.cjs';
17
17
  import 'node:http';
18
18
 
19
19
  declare class DiscoveryDocumentCache {
package/dist/FastMCP.d.ts CHANGED
@@ -12,8 +12,8 @@ import { CorsOptions } from 'mcp-proxy';
12
12
  export { CorsOptions } from 'mcp-proxy';
13
13
  import { StrictEventEmitter } from 'strict-event-emitter-types';
14
14
  import { z } from 'zod';
15
- import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-B_OJFNC0.js';
16
- export { j as AuthProviderConfig, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, d as OAuthProvider, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from './OAuthProvider-B_OJFNC0.js';
15
+ import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-Bvt5a7yr.js';
16
+ export { j as AuthProviderConfig, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, d as OAuthProvider, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from './OAuthProvider-Bvt5a7yr.js';
17
17
  import 'node:http';
18
18
 
19
19
  declare class DiscoveryDocumentCache {
package/dist/FastMCP.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  requireAuth,
25
25
  requireRole,
26
26
  requireScopes
27
- } from "./chunk-VFBUPSNI.js";
27
+ } from "./chunk-ZOG7IPIX.js";
28
28
  export {
29
29
  AuthProvider,
30
30
  AzureProvider,
@@ -205,6 +205,22 @@ interface OAuthProxyConfig {
205
205
  * https URLs enables CWE-601 open-redirect / authorization-code theft.
206
206
  */
207
207
  allowedRedirectUriPatterns?: string[];
208
+ /**
209
+ * Accept `code_challenge_method=plain` at /oauth/authorize (default: true).
210
+ *
211
+ * `plain` is the weaker PKCE mode by RFC 7636 §7.2: the challenge *is* the
212
+ * verifier, so anyone who observes the authorization request — a proxy, a
213
+ * server log, browser history — can replay a stolen authorization code. S256
214
+ * sends only a hash and has no such exposure. OAuth 2.1 §7.5.2 and the MCP
215
+ * authorization spec both require S256.
216
+ *
217
+ * Set to `false` to refuse `plain`: it is dropped from
218
+ * `codeChallengeMethodsSupported` in the discovery metadata, rejected with
219
+ * `invalid_request` at /oauth/authorize, and any code already issued under it
220
+ * is refused at /oauth/token. Recommended for new deployments; it stays on by
221
+ * default because turning it off breaks clients that still ask for `plain`.
222
+ */
223
+ allowPlainPkce?: boolean;
208
224
  /** Authorization code TTL in seconds (default: 300) */
209
225
  authorizationCodeTtl?: number;
210
226
  /** Base URL of this proxy server */
@@ -454,6 +470,14 @@ declare class OAuthProxy {
454
470
  private config;
455
471
  private consentManager;
456
472
  private jwtIssuer?;
473
+ /**
474
+ * The fallback storage this proxy created for itself, if any. It runs a
475
+ * cleanup timer that keeps the event loop alive, so `destroy()` has to stop
476
+ * it — and once the storage is wrapped for encryption it is reachable
477
+ * through nothing else. A caller-supplied storage is deliberately not
478
+ * recorded here: its lifetime belongs to the caller.
479
+ */
480
+ private ownedTokenStorage;
457
481
  /**
458
482
  * Keyed by proxy-issued client_id for authorize/token-exchange lookups and
459
483
  * for the defence-in-depth callback checks. A registration never changes
@@ -205,6 +205,22 @@ interface OAuthProxyConfig {
205
205
  * https URLs enables CWE-601 open-redirect / authorization-code theft.
206
206
  */
207
207
  allowedRedirectUriPatterns?: string[];
208
+ /**
209
+ * Accept `code_challenge_method=plain` at /oauth/authorize (default: true).
210
+ *
211
+ * `plain` is the weaker PKCE mode by RFC 7636 §7.2: the challenge *is* the
212
+ * verifier, so anyone who observes the authorization request — a proxy, a
213
+ * server log, browser history — can replay a stolen authorization code. S256
214
+ * sends only a hash and has no such exposure. OAuth 2.1 §7.5.2 and the MCP
215
+ * authorization spec both require S256.
216
+ *
217
+ * Set to `false` to refuse `plain`: it is dropped from
218
+ * `codeChallengeMethodsSupported` in the discovery metadata, rejected with
219
+ * `invalid_request` at /oauth/authorize, and any code already issued under it
220
+ * is refused at /oauth/token. Recommended for new deployments; it stays on by
221
+ * default because turning it off breaks clients that still ask for `plain`.
222
+ */
223
+ allowPlainPkce?: boolean;
208
224
  /** Authorization code TTL in seconds (default: 300) */
209
225
  authorizationCodeTtl?: number;
210
226
  /** Base URL of this proxy server */
@@ -454,6 +470,14 @@ declare class OAuthProxy {
454
470
  private config;
455
471
  private consentManager;
456
472
  private jwtIssuer?;
473
+ /**
474
+ * The fallback storage this proxy created for itself, if any. It runs a
475
+ * cleanup timer that keeps the event loop alive, so `destroy()` has to stop
476
+ * it — and once the storage is wrapped for encryption it is reachable
477
+ * through nothing else. A caller-supplied storage is deliberately not
478
+ * recorded here: its lifetime belongs to the caller.
479
+ */
480
+ private ownedTokenStorage;
457
481
  /**
458
482
  * Keyed by proxy-issued client_id for authorize/token-exchange lookups and
459
483
  * for the defence-in-depth callback checks. A registration never changes
@@ -24,7 +24,7 @@
24
24
 
25
25
 
26
26
 
27
- var _chunk6DTYLKSCcjs = require('../chunk-6DTYLKSC.cjs');
27
+ var _chunk5FVNY65Mcjs = require('../chunk-5FVNY65M.cjs');
28
28
 
29
29
 
30
30
 
@@ -51,5 +51,5 @@ var _chunk6DTYLKSCcjs = require('../chunk-6DTYLKSC.cjs');
51
51
 
52
52
 
53
53
 
54
- exports.AuthProvider = _chunk6DTYLKSCcjs.AuthProvider; exports.AzureProvider = _chunk6DTYLKSCcjs.AzureProvider; exports.ConsentManager = _chunk6DTYLKSCcjs.ConsentManager; exports.DEFAULT_ACCESS_TOKEN_TTL = _chunk6DTYLKSCcjs.DEFAULT_ACCESS_TOKEN_TTL; exports.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH = _chunk6DTYLKSCcjs.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH; exports.DEFAULT_AUTHORIZATION_CODE_TTL = _chunk6DTYLKSCcjs.DEFAULT_AUTHORIZATION_CODE_TTL; exports.DEFAULT_REFRESH_TOKEN_TTL = _chunk6DTYLKSCcjs.DEFAULT_REFRESH_TOKEN_TTL; exports.DEFAULT_TRANSACTION_TTL = _chunk6DTYLKSCcjs.DEFAULT_TRANSACTION_TTL; exports.DiskStore = _chunk6DTYLKSCcjs.DiskStore; exports.EncryptedTokenStorage = _chunk6DTYLKSCcjs.EncryptedTokenStorage; exports.GitHubProvider = _chunk6DTYLKSCcjs.GitHubProvider; exports.GoogleProvider = _chunk6DTYLKSCcjs.GoogleProvider; exports.JWKSVerifier = _chunk6DTYLKSCcjs.JWKSVerifier; exports.JWTIssuer = _chunk6DTYLKSCcjs.JWTIssuer; exports.MemoryTokenStorage = _chunk6DTYLKSCcjs.MemoryTokenStorage; exports.OAuthProvider = _chunk6DTYLKSCcjs.OAuthProvider; exports.OAuthProxy = _chunk6DTYLKSCcjs.OAuthProxy; exports.OAuthProxyError = _chunk6DTYLKSCcjs.OAuthProxyError; exports.PKCEUtils = _chunk6DTYLKSCcjs.PKCEUtils; exports.getAuthSession = _chunk6DTYLKSCcjs.getAuthSession; exports.requireAll = _chunk6DTYLKSCcjs.requireAll; exports.requireAny = _chunk6DTYLKSCcjs.requireAny; exports.requireAuth = _chunk6DTYLKSCcjs.requireAuth; exports.requireRole = _chunk6DTYLKSCcjs.requireRole; exports.requireScopes = _chunk6DTYLKSCcjs.requireScopes;
54
+ exports.AuthProvider = _chunk5FVNY65Mcjs.AuthProvider; exports.AzureProvider = _chunk5FVNY65Mcjs.AzureProvider; exports.ConsentManager = _chunk5FVNY65Mcjs.ConsentManager; exports.DEFAULT_ACCESS_TOKEN_TTL = _chunk5FVNY65Mcjs.DEFAULT_ACCESS_TOKEN_TTL; exports.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH = _chunk5FVNY65Mcjs.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH; exports.DEFAULT_AUTHORIZATION_CODE_TTL = _chunk5FVNY65Mcjs.DEFAULT_AUTHORIZATION_CODE_TTL; exports.DEFAULT_REFRESH_TOKEN_TTL = _chunk5FVNY65Mcjs.DEFAULT_REFRESH_TOKEN_TTL; exports.DEFAULT_TRANSACTION_TTL = _chunk5FVNY65Mcjs.DEFAULT_TRANSACTION_TTL; exports.DiskStore = _chunk5FVNY65Mcjs.DiskStore; exports.EncryptedTokenStorage = _chunk5FVNY65Mcjs.EncryptedTokenStorage; exports.GitHubProvider = _chunk5FVNY65Mcjs.GitHubProvider; exports.GoogleProvider = _chunk5FVNY65Mcjs.GoogleProvider; exports.JWKSVerifier = _chunk5FVNY65Mcjs.JWKSVerifier; exports.JWTIssuer = _chunk5FVNY65Mcjs.JWTIssuer; exports.MemoryTokenStorage = _chunk5FVNY65Mcjs.MemoryTokenStorage; exports.OAuthProvider = _chunk5FVNY65Mcjs.OAuthProvider; exports.OAuthProxy = _chunk5FVNY65Mcjs.OAuthProxy; exports.OAuthProxyError = _chunk5FVNY65Mcjs.OAuthProxyError; exports.PKCEUtils = _chunk5FVNY65Mcjs.PKCEUtils; exports.getAuthSession = _chunk5FVNY65Mcjs.getAuthSession; exports.requireAll = _chunk5FVNY65Mcjs.requireAll; exports.requireAny = _chunk5FVNY65Mcjs.requireAny; exports.requireAuth = _chunk5FVNY65Mcjs.requireAuth; exports.requireRole = _chunk5FVNY65Mcjs.requireRole; exports.requireScopes = _chunk5FVNY65Mcjs.requireScopes;
55
55
  //# sourceMappingURL=index.cjs.map
@@ -1,5 +1,5 @@
1
- import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-B_OJFNC0.cjs';
2
- export { A as AuthProvider, j as AuthProviderConfig, y as AuthorizationParams, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, z as ClientCode, B as DCRClientMetadata, E as DCRRequest, F as DCRResponse, D as DEFAULT_ACCESS_TOKEN_TTL, u as DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH, v as DEFAULT_AUTHORIZATION_CODE_TTL, w as DEFAULT_REFRESH_TOKEN_TTL, x as DEFAULT_TRANSACTION_TTL, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, H as OAuthError, d as OAuthProvider, I as OAuthProviderConfig, a as OAuthProxy, J as OAuthProxyConfig, t as OAuthProxyError, O as OAuthSession, K as ProxyDCRClient, R as RefreshRequest, L as TokenMapping, M as TokenRequest, N as TokenResponse, U as UpstreamTokenSet, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from '../OAuthProvider-B_OJFNC0.cjs';
1
+ import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-Bvt5a7yr.cjs';
2
+ export { A as AuthProvider, j as AuthProviderConfig, y as AuthorizationParams, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, z as ClientCode, B as DCRClientMetadata, E as DCRRequest, F as DCRResponse, D as DEFAULT_ACCESS_TOKEN_TTL, u as DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH, v as DEFAULT_AUTHORIZATION_CODE_TTL, w as DEFAULT_REFRESH_TOKEN_TTL, x as DEFAULT_TRANSACTION_TTL, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, H as OAuthError, d as OAuthProvider, I as OAuthProviderConfig, a as OAuthProxy, J as OAuthProxyConfig, t as OAuthProxyError, O as OAuthSession, K as ProxyDCRClient, R as RefreshRequest, L as TokenMapping, M as TokenRequest, N as TokenResponse, U as UpstreamTokenSet, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from '../OAuthProvider-Bvt5a7yr.cjs';
3
3
  import 'node:http';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-B_OJFNC0.js';
2
- export { A as AuthProvider, j as AuthProviderConfig, y as AuthorizationParams, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, z as ClientCode, B as DCRClientMetadata, E as DCRRequest, F as DCRResponse, D as DEFAULT_ACCESS_TOKEN_TTL, u as DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH, v as DEFAULT_AUTHORIZATION_CODE_TTL, w as DEFAULT_REFRESH_TOKEN_TTL, x as DEFAULT_TRANSACTION_TTL, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, H as OAuthError, d as OAuthProvider, I as OAuthProviderConfig, a as OAuthProxy, J as OAuthProxyConfig, t as OAuthProxyError, O as OAuthSession, K as ProxyDCRClient, R as RefreshRequest, L as TokenMapping, M as TokenRequest, N as TokenResponse, U as UpstreamTokenSet, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from '../OAuthProvider-B_OJFNC0.js';
1
+ import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-Bvt5a7yr.js';
2
+ export { A as AuthProvider, j as AuthProviderConfig, y as AuthorizationParams, b as AzureProvider, k as AzureProviderConfig, l as AzureSession, z as ClientCode, B as DCRClientMetadata, E as DCRRequest, F as DCRResponse, D as DEFAULT_ACCESS_TOKEN_TTL, u as DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH, v as DEFAULT_AUTHORIZATION_CODE_TTL, w as DEFAULT_REFRESH_TOKEN_TTL, x as DEFAULT_TRANSACTION_TTL, m as GenericOAuthProviderConfig, G as GitHubProvider, n as GitHubSession, c as GoogleProvider, o as GoogleSession, H as OAuthError, d as OAuthProvider, I as OAuthProviderConfig, a as OAuthProxy, J as OAuthProxyConfig, t as OAuthProxyError, O as OAuthSession, K as ProxyDCRClient, R as RefreshRequest, L as TokenMapping, M as TokenRequest, N as TokenResponse, U as UpstreamTokenSet, g as getAuthSession, r as requireAll, e as requireAny, f as requireAuth, h as requireRole, i as requireScopes } from '../OAuthProvider-Bvt5a7yr.js';
3
3
  import 'node:http';
4
4
 
5
5
  /**
@@ -24,7 +24,7 @@ import {
24
24
  requireAuth,
25
25
  requireRole,
26
26
  requireScopes
27
- } from "../chunk-VFBUPSNI.js";
27
+ } from "../chunk-ZOG7IPIX.js";
28
28
  export {
29
29
  AuthProvider,
30
30
  AzureProvider,
@@ -419,6 +419,16 @@ var ClaimsExtractor = (_class = class {
419
419
 
420
420
  // src/auth/utils/consent.ts
421
421
 
422
+
423
+ // src/auth/utils/constantTime.ts
424
+
425
+ function equalsConstantTime(a, b) {
426
+ const bufA = Buffer.from(a, "utf8");
427
+ const bufB = Buffer.from(b, "utf8");
428
+ return bufA.length === bufB.length && _crypto.timingSafeEqual.call(void 0, bufA, bufB);
429
+ }
430
+
431
+ // src/auth/utils/consent.ts
422
432
  var ConsentManager = class {
423
433
 
424
434
  constructor(signingKey) {
@@ -671,9 +681,7 @@ var ConsentManager = class {
671
681
  }
672
682
  const payload = Buffer.from(payloadB64, "base64").toString("utf8");
673
683
  const expectedSignature = this.sign(payload);
674
- const actualBuf = Buffer.from(signature);
675
- const expectedBuf = Buffer.from(expectedSignature);
676
- if (actualBuf.length !== expectedBuf.length || !_crypto.timingSafeEqual.call(void 0, actualBuf, expectedBuf)) {
684
+ if (!equalsConstantTime(signature, expectedSignature)) {
677
685
  return null;
678
686
  }
679
687
  const data = JSON.parse(payload);
@@ -805,9 +813,7 @@ var JWTIssuer = class {
805
813
  }
806
814
  const [headerB64, payloadB64, signatureB64] = parts;
807
815
  const expectedSignature = this.sign(`${headerB64}.${payloadB64}`);
808
- const actualBuf = Buffer.from(signatureB64);
809
- const expectedBuf = Buffer.from(expectedSignature);
810
- if (actualBuf.length !== expectedBuf.length || !_crypto.timingSafeEqual.call(void 0, actualBuf, expectedBuf)) {
816
+ if (!signatureB64 || !equalsConstantTime(signatureB64, expectedSignature)) {
811
817
  return {
812
818
  error: "Invalid signature",
813
819
  valid: false
@@ -955,11 +961,6 @@ var PKCEUtils = class _PKCEUtils {
955
961
  return buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
956
962
  }
957
963
  };
958
- function equalsConstantTime(a, b) {
959
- const bufA = Buffer.from(a, "utf8");
960
- const bufB = Buffer.from(b, "utf8");
961
- return bufA.length === bufB.length && _crypto.timingSafeEqual.call(void 0, bufA, bufB);
962
- }
963
964
 
964
965
  // src/auth/utils/tokenStore.ts
965
966
 
@@ -1140,17 +1141,26 @@ var OAuthProxy = (_class4 = class {
1140
1141
 
1141
1142
 
1142
1143
 
1144
+ /**
1145
+ * The fallback storage this proxy created for itself, if any. It runs a
1146
+ * cleanup timer that keeps the event loop alive, so `destroy()` has to stop
1147
+ * it — and once the storage is wrapped for encryption it is reachable
1148
+ * through nothing else. A caller-supplied storage is deliberately not
1149
+ * recorded here: its lifetime belongs to the caller.
1150
+ */
1151
+ __init7() {this.ownedTokenStorage = null}
1143
1152
  /**
1144
1153
  * Keyed by proxy-issued client_id for authorize/token-exchange lookups and
1145
1154
  * for the defence-in-depth callback checks. A registration never changes
1146
1155
  * after it is written, so caching it locally cannot go stale; it is also
1147
1156
  * persisted, so another instance can hydrate it.
1148
1157
  */
1149
- __init7() {this.registeredClientsByClientId = /* @__PURE__ */ new Map()}
1158
+ __init8() {this.registeredClientsByClientId = /* @__PURE__ */ new Map()}
1150
1159
 
1151
1160
 
1152
- constructor(config) {;_class4.prototype.__init5.call(this);_class4.prototype.__init6.call(this);_class4.prototype.__init7.call(this);
1161
+ constructor(config) {;_class4.prototype.__init5.call(this);_class4.prototype.__init6.call(this);_class4.prototype.__init7.call(this);_class4.prototype.__init8.call(this);
1153
1162
  this.config = {
1163
+ allowPlainPkce: true,
1154
1164
  authorizationCodeTtl: DEFAULT_AUTHORIZATION_CODE_TTL,
1155
1165
  consentRequired: true,
1156
1166
  enableTokenSwap: true,
@@ -1161,7 +1171,11 @@ var OAuthProxy = (_class4 = class {
1161
1171
  upstreamTokenEndpointAuthMethod: "client_secret_basic",
1162
1172
  ...config
1163
1173
  };
1164
- let storage = config.tokenStorage || new MemoryTokenStorage();
1174
+ let storage = config.tokenStorage;
1175
+ if (!storage) {
1176
+ this.ownedTokenStorage = new MemoryTokenStorage();
1177
+ storage = this.ownedTokenStorage;
1178
+ }
1165
1179
  const isAlreadyEncrypted = storage.constructor.name === "EncryptedTokenStorage";
1166
1180
  if (!isAlreadyEncrypted && config.encryptionKey !== false) {
1167
1181
  const encryptionKey = typeof config.encryptionKey === "string" ? config.encryptionKey : this.generateSigningKey();
@@ -1221,6 +1235,12 @@ var OAuthProxy = (_class4 = class {
1221
1235
  "code_challenge_method required when code_challenge is present"
1222
1236
  );
1223
1237
  }
1238
+ if (params.code_challenge_method === "plain" && !this.config.allowPlainPkce) {
1239
+ throw new OAuthProxyError(
1240
+ "invalid_request",
1241
+ "code_challenge_method 'plain' is not supported; use S256"
1242
+ );
1243
+ }
1224
1244
  const transaction = await this.createTransaction(params);
1225
1245
  if (this.config.consentRequired && !transaction.consentGiven) {
1226
1246
  return this.consentManager.createConsentResponse(
@@ -1238,6 +1258,7 @@ var OAuthProxy = (_class4 = class {
1238
1258
  clearInterval(this.cleanupInterval);
1239
1259
  this.cleanupInterval = null;
1240
1260
  }
1261
+ _optionalChain([this, 'access', _8 => _8.ownedTokenStorage, 'optionalAccess', _9 => _9.destroy, 'call', _10 => _10()]);
1241
1262
  this.registeredClientsByClientId.clear();
1242
1263
  }
1243
1264
  /**
@@ -1279,6 +1300,12 @@ var OAuthProxy = (_class4 = class {
1279
1300
  "code_verifier required for PKCE"
1280
1301
  );
1281
1302
  }
1303
+ if (clientCode.codeChallengeMethod === "plain" && !this.config.allowPlainPkce) {
1304
+ throw new OAuthProxyError(
1305
+ "invalid_grant",
1306
+ "code_challenge_method 'plain' is not supported; use S256"
1307
+ );
1308
+ }
1282
1309
  const valid = PKCEUtils.validateChallenge(
1283
1310
  request.code_verifier,
1284
1311
  clientCode.codeChallenge,
@@ -1332,7 +1359,7 @@ var OAuthProxy = (_class4 = class {
1332
1359
  getAuthorizationServerMetadata() {
1333
1360
  return {
1334
1361
  authorizationEndpoint: `${this.config.baseUrl}/oauth/authorize`,
1335
- codeChallengeMethodsSupported: ["S256", "plain"],
1362
+ codeChallengeMethodsSupported: this.config.allowPlainPkce ? ["S256", "plain"] : ["S256"],
1336
1363
  grantTypesSupported: ["authorization_code", "refresh_token"],
1337
1364
  issuer: this.config.baseUrl,
1338
1365
  registrationEndpoint: `${this.config.baseUrl}/oauth/register`,
@@ -1448,7 +1475,7 @@ var OAuthProxy = (_class4 = class {
1448
1475
  return null;
1449
1476
  }
1450
1477
  const result = await this.jwtIssuer.verify(fastmcpToken);
1451
- if (!result.valid || !_optionalChain([result, 'access', _8 => _8.claims, 'optionalAccess', _9 => _9.jti])) {
1478
+ if (!result.valid || !_optionalChain([result, 'access', _11 => _11.claims, 'optionalAccess', _12 => _12.jti])) {
1452
1479
  return null;
1453
1480
  }
1454
1481
  const mapping = await this.tokenStorage.get(
@@ -1635,7 +1662,7 @@ var OAuthProxy = (_class4 = class {
1635
1662
  throw new Error("JWT issuer not initialized");
1636
1663
  }
1637
1664
  const result = await this.jwtIssuer.verify(token);
1638
- if (!result.valid || !_optionalChain([result, 'access', _10 => _10.claims, 'optionalAccess', _11 => _11.jti])) {
1665
+ if (!result.valid || !_optionalChain([result, 'access', _13 => _13.claims, 'optionalAccess', _14 => _14.jti])) {
1639
1666
  throw new Error("Failed to extract JTI from token");
1640
1667
  }
1641
1668
  return result.claims.jti;
@@ -1803,7 +1830,7 @@ var OAuthProxy = (_class4 = class {
1803
1830
  "Invalid or expired refresh token"
1804
1831
  );
1805
1832
  }
1806
- const jti = _optionalChain([verifyResult, 'access', _12 => _12.claims, 'optionalAccess', _13 => _13.jti]);
1833
+ const jti = _optionalChain([verifyResult, 'access', _15 => _15.claims, 'optionalAccess', _16 => _16.jti]);
1807
1834
  if (!jti) {
1808
1835
  throw new OAuthProxyError("invalid_grant", "Refresh token missing JTI");
1809
1836
  }
@@ -2252,7 +2279,7 @@ var AuthProvider = class {
2252
2279
  if (!request) {
2253
2280
  return void 0;
2254
2281
  }
2255
- const authHeader = _optionalChain([request, 'access', _14 => _14.headers, 'optionalAccess', _15 => _15.authorization]);
2282
+ const authHeader = _optionalChain([request, 'access', _17 => _17.headers, 'optionalAccess', _18 => _18.authorization]);
2256
2283
  if (!authHeader || !authHeader.startsWith("Bearer ")) {
2257
2284
  return void 0;
2258
2285
  }
@@ -2453,10 +2480,10 @@ var OAuthProvider = class extends AuthProvider {
2453
2480
  var _promises = require('fs/promises');
2454
2481
  var _path = require('path');
2455
2482
  var DiskStore = (_class5 = class {
2456
- __init8() {this.cleanupInterval = null}
2483
+ __init9() {this.cleanupInterval = null}
2457
2484
 
2458
2485
 
2459
- constructor(options) {;_class5.prototype.__init8.call(this);
2486
+ constructor(options) {;_class5.prototype.__init9.call(this);
2460
2487
  this.directory = options.directory;
2461
2488
  this.fileExtension = options.fileExtension || ".json";
2462
2489
  void this.ensureDirectory();
@@ -2629,9 +2656,9 @@ var DiskStore = (_class5 = class {
2629
2656
  var JWKSVerifier = (_class6 = class {
2630
2657
 
2631
2658
 
2632
- __init9() {this.joseLoaded = false}
2659
+ __init10() {this.joseLoaded = false}
2633
2660
 
2634
- constructor(config) {;_class6.prototype.__init9.call(this);
2661
+ constructor(config) {;_class6.prototype.__init10.call(this);
2635
2662
  this.config = {
2636
2663
  cacheDuration: 36e5,
2637
2664
  // 1 hour
@@ -2789,4 +2816,4 @@ Original error: ${error.message}`
2789
2816
 
2790
2817
 
2791
2818
  exports.getAuthSession = getAuthSession; exports.requireAll = requireAll; exports.requireAny = requireAny; exports.requireAuth = requireAuth; exports.requireRole = requireRole; exports.requireScopes = requireScopes; exports.DEFAULT_ACCESS_TOKEN_TTL = DEFAULT_ACCESS_TOKEN_TTL; exports.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH = DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH; exports.DEFAULT_REFRESH_TOKEN_TTL = DEFAULT_REFRESH_TOKEN_TTL; exports.DEFAULT_AUTHORIZATION_CODE_TTL = DEFAULT_AUTHORIZATION_CODE_TTL; exports.DEFAULT_TRANSACTION_TTL = DEFAULT_TRANSACTION_TTL; exports.ConsentManager = ConsentManager; exports.JWTIssuer = JWTIssuer; exports.PKCEUtils = PKCEUtils; exports.EncryptedTokenStorage = EncryptedTokenStorage; exports.MemoryTokenStorage = MemoryTokenStorage; exports.OAuthProxy = OAuthProxy; exports.OAuthProxyError = OAuthProxyError; exports.AuthProvider = AuthProvider; exports.AzureProvider = AzureProvider; exports.GitHubProvider = GitHubProvider; exports.GoogleProvider = GoogleProvider; exports.OAuthProvider = OAuthProvider; exports.DiskStore = DiskStore; exports.JWKSVerifier = JWKSVerifier;
2792
- //# sourceMappingURL=chunk-6DTYLKSC.cjs.map
2819
+ //# sourceMappingURL=chunk-5FVNY65M.cjs.map