fastmcp 3.35.0 → 4.0.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
@@ -20,7 +20,7 @@ var _chunkJP7QSER3cjs = require('./chunk-JP7QSER3.cjs');
20
20
 
21
21
 
22
22
 
23
- var _chunk7UDY4VFQcjs = require('./chunk-7UDY4VFQ.cjs');
23
+ var _chunkSSVFQCSNcjs = require('./chunk-SSVFQCSN.cjs');
24
24
 
25
25
 
26
26
 
@@ -41,5 +41,5 @@ var _chunk7UDY4VFQcjs = require('./chunk-7UDY4VFQ.cjs');
41
41
 
42
42
 
43
43
 
44
- exports.AuthProvider = _chunk7UDY4VFQcjs.AuthProvider; exports.AzureProvider = _chunk7UDY4VFQcjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkJP7QSER3cjs.DiscoveryDocumentCache; exports.FastMCP = _chunkJP7QSER3cjs.FastMCP; exports.FastMCPSession = _chunkJP7QSER3cjs.FastMCPSession; exports.GitHubProvider = _chunk7UDY4VFQcjs.GitHubProvider; exports.GoogleProvider = _chunk7UDY4VFQcjs.GoogleProvider; exports.OAuthProvider = _chunk7UDY4VFQcjs.OAuthProvider; exports.ServerState = _chunkJP7QSER3cjs.ServerState; exports.UnexpectedStateError = _chunkJP7QSER3cjs.UnexpectedStateError; exports.UserError = _chunkJP7QSER3cjs.UserError; exports.audioContent = _chunkJP7QSER3cjs.audioContent; exports.getAuthSession = _chunk7UDY4VFQcjs.getAuthSession; exports.imageContent = _chunkJP7QSER3cjs.imageContent; exports.requireAll = _chunk7UDY4VFQcjs.requireAll; exports.requireAny = _chunk7UDY4VFQcjs.requireAny; exports.requireAuth = _chunk7UDY4VFQcjs.requireAuth; exports.requireRole = _chunk7UDY4VFQcjs.requireRole; exports.requireScopes = _chunk7UDY4VFQcjs.requireScopes;
44
+ exports.AuthProvider = _chunkSSVFQCSNcjs.AuthProvider; exports.AzureProvider = _chunkSSVFQCSNcjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkJP7QSER3cjs.DiscoveryDocumentCache; exports.FastMCP = _chunkJP7QSER3cjs.FastMCP; exports.FastMCPSession = _chunkJP7QSER3cjs.FastMCPSession; exports.GitHubProvider = _chunkSSVFQCSNcjs.GitHubProvider; exports.GoogleProvider = _chunkSSVFQCSNcjs.GoogleProvider; exports.OAuthProvider = _chunkSSVFQCSNcjs.OAuthProvider; exports.ServerState = _chunkJP7QSER3cjs.ServerState; exports.UnexpectedStateError = _chunkJP7QSER3cjs.UnexpectedStateError; exports.UserError = _chunkJP7QSER3cjs.UserError; exports.audioContent = _chunkJP7QSER3cjs.audioContent; exports.getAuthSession = _chunkSSVFQCSNcjs.getAuthSession; exports.imageContent = _chunkJP7QSER3cjs.imageContent; exports.requireAll = _chunkSSVFQCSNcjs.requireAll; exports.requireAny = _chunkSSVFQCSNcjs.requireAny; exports.requireAuth = _chunkSSVFQCSNcjs.requireAuth; exports.requireRole = _chunkSSVFQCSNcjs.requireRole; exports.requireScopes = _chunkSSVFQCSNcjs.requireScopes;
45
45
  //# sourceMappingURL=FastMCP.cjs.map
@@ -10,8 +10,8 @@ import { Hono } from 'hono';
10
10
  import http from 'http';
11
11
  import { StrictEventEmitter } from 'strict-event-emitter-types';
12
12
  import { z } from 'zod';
13
- import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-R8buLRa8.cjs';
14
- 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-R8buLRa8.cjs';
13
+ import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-BV6EpF_k.cjs';
14
+ 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-BV6EpF_k.cjs';
15
15
  import 'node:http';
16
16
 
17
17
  declare class DiscoveryDocumentCache {
package/dist/FastMCP.d.ts CHANGED
@@ -10,8 +10,8 @@ import { Hono } from 'hono';
10
10
  import http from 'http';
11
11
  import { StrictEventEmitter } from 'strict-event-emitter-types';
12
12
  import { z } from 'zod';
13
- import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-R8buLRa8.js';
14
- 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-R8buLRa8.js';
13
+ import { A as AuthProvider, O as OAuthSession, a as OAuthProxy } from './OAuthProvider-BV6EpF_k.js';
14
+ 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-BV6EpF_k.js';
15
15
  import 'node:http';
16
16
 
17
17
  declare class DiscoveryDocumentCache {
package/dist/FastMCP.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  requireAuth,
21
21
  requireRole,
22
22
  requireScopes
23
- } from "./chunk-H4VC4YTC.js";
23
+ } from "./chunk-UN72PIH2.js";
24
24
  export {
25
25
  AuthProvider,
26
26
  AzureProvider,
@@ -185,7 +185,23 @@ interface OAuthProviderConfig {
185
185
  interface OAuthProxyConfig {
186
186
  /** Access token TTL in seconds (default: 3600) */
187
187
  accessTokenTtl?: number;
188
- /** Allowed redirect URI patterns for client registration */
188
+ /**
189
+ * Allow-list of redirect URI patterns accepted by Dynamic Client Registration.
190
+ *
191
+ * A client calling POST /oauth/register must present a `redirect_uri` that
192
+ * matches one of these patterns (exact string or glob with `*` / `?`);
193
+ * otherwise the registration is rejected with `invalid_redirect_uri`. Once
194
+ * registered, the same exact URI must be echoed back at /oauth/authorize —
195
+ * the proxy performs exact string comparison per RFC 6749 §3.1.2.3.
196
+ *
197
+ * Default: `[]` (DCR rejects everything — explicit opt-in required).
198
+ *
199
+ * Prior versions defaulted to `["https://*", "http://localhost:*"]` with an
200
+ * implicit fallback that allowed any https URL. This enabled CWE-601
201
+ * open-redirect / authorization-code theft: an attacker could DCR their own
202
+ * URL and then steal victim codes via /oauth/authorize. Do not loosen this
203
+ * default without understanding that threat model.
204
+ */
189
205
  allowedRedirectUriPatterns?: string[];
190
206
  /** Authorization code TTL in seconds (default: 300) */
191
207
  authorizationCodeTtl?: number;
@@ -548,7 +564,16 @@ declare class OAuthProxy {
548
564
  */
549
565
  private startCleanup;
550
566
  /**
551
- * Validate redirect URI against allowed patterns
567
+ * Validate a redirect URI against the configured allow-list.
568
+ *
569
+ * Returns `true` only if the URI is syntactically valid AND matches one of
570
+ * the explicitly configured `allowedRedirectUriPatterns`. An empty or unset
571
+ * pattern list means DCR will reject every URI — framework users must
572
+ * opt-in by listing the exact URIs (or wildcards) they trust.
573
+ *
574
+ * Prior versions also fell back to allowing any https URL or localhost,
575
+ * which enabled attackers to DCR an arbitrary URL and then abuse it via
576
+ * /oauth/authorize (CWE-601). Do not re-introduce that fallback.
552
577
  */
553
578
  private validateRedirectUri;
554
579
  }
@@ -573,7 +598,17 @@ declare class OAuthProxyError extends Error {
573
598
  * Configuration common to all OAuth providers.
574
599
  */
575
600
  interface AuthProviderConfig {
576
- /** Allowed redirect URI patterns (default: ["http://localhost:*", "https://*"]) */
601
+ /**
602
+ * Allow-list of redirect URI patterns accepted by Dynamic Client
603
+ * Registration. Required for any deployment that exposes /oauth/register
604
+ * or /oauth/authorize — an empty/unset list rejects every URI.
605
+ *
606
+ * Example: `["https://yourapp.example.com/*"]`
607
+ *
608
+ * Prior versions defaulted to `["http://localhost:*", "https://*"]`, which
609
+ * enabled CWE-601 open-redirect / authorization-code theft. See the
610
+ * SECURITY advisory before loosening this.
611
+ */
577
612
  allowedRedirectUriPatterns?: string[];
578
613
  /** Base URL where the MCP server is accessible */
579
614
  baseUrl: string;
@@ -185,7 +185,23 @@ interface OAuthProviderConfig {
185
185
  interface OAuthProxyConfig {
186
186
  /** Access token TTL in seconds (default: 3600) */
187
187
  accessTokenTtl?: number;
188
- /** Allowed redirect URI patterns for client registration */
188
+ /**
189
+ * Allow-list of redirect URI patterns accepted by Dynamic Client Registration.
190
+ *
191
+ * A client calling POST /oauth/register must present a `redirect_uri` that
192
+ * matches one of these patterns (exact string or glob with `*` / `?`);
193
+ * otherwise the registration is rejected with `invalid_redirect_uri`. Once
194
+ * registered, the same exact URI must be echoed back at /oauth/authorize —
195
+ * the proxy performs exact string comparison per RFC 6749 §3.1.2.3.
196
+ *
197
+ * Default: `[]` (DCR rejects everything — explicit opt-in required).
198
+ *
199
+ * Prior versions defaulted to `["https://*", "http://localhost:*"]` with an
200
+ * implicit fallback that allowed any https URL. This enabled CWE-601
201
+ * open-redirect / authorization-code theft: an attacker could DCR their own
202
+ * URL and then steal victim codes via /oauth/authorize. Do not loosen this
203
+ * default without understanding that threat model.
204
+ */
189
205
  allowedRedirectUriPatterns?: string[];
190
206
  /** Authorization code TTL in seconds (default: 300) */
191
207
  authorizationCodeTtl?: number;
@@ -548,7 +564,16 @@ declare class OAuthProxy {
548
564
  */
549
565
  private startCleanup;
550
566
  /**
551
- * Validate redirect URI against allowed patterns
567
+ * Validate a redirect URI against the configured allow-list.
568
+ *
569
+ * Returns `true` only if the URI is syntactically valid AND matches one of
570
+ * the explicitly configured `allowedRedirectUriPatterns`. An empty or unset
571
+ * pattern list means DCR will reject every URI — framework users must
572
+ * opt-in by listing the exact URIs (or wildcards) they trust.
573
+ *
574
+ * Prior versions also fell back to allowing any https URL or localhost,
575
+ * which enabled attackers to DCR an arbitrary URL and then abuse it via
576
+ * /oauth/authorize (CWE-601). Do not re-introduce that fallback.
552
577
  */
553
578
  private validateRedirectUri;
554
579
  }
@@ -573,7 +598,17 @@ declare class OAuthProxyError extends Error {
573
598
  * Configuration common to all OAuth providers.
574
599
  */
575
600
  interface AuthProviderConfig {
576
- /** Allowed redirect URI patterns (default: ["http://localhost:*", "https://*"]) */
601
+ /**
602
+ * Allow-list of redirect URI patterns accepted by Dynamic Client
603
+ * Registration. Required for any deployment that exposes /oauth/register
604
+ * or /oauth/authorize — an empty/unset list rejects every URI.
605
+ *
606
+ * Example: `["https://yourapp.example.com/*"]`
607
+ *
608
+ * Prior versions defaulted to `["http://localhost:*", "https://*"]`, which
609
+ * enabled CWE-601 open-redirect / authorization-code theft. See the
610
+ * SECURITY advisory before loosening this.
611
+ */
577
612
  allowedRedirectUriPatterns?: string[];
578
613
  /** Base URL where the MCP server is accessible */
579
614
  baseUrl: string;
@@ -24,7 +24,7 @@
24
24
 
25
25
 
26
26
 
27
- var _chunk7UDY4VFQcjs = require('../chunk-7UDY4VFQ.cjs');
27
+ var _chunkSSVFQCSNcjs = require('../chunk-SSVFQCSN.cjs');
28
28
 
29
29
 
30
30
 
@@ -51,5 +51,5 @@ var _chunk7UDY4VFQcjs = require('../chunk-7UDY4VFQ.cjs');
51
51
 
52
52
 
53
53
 
54
- exports.AuthProvider = _chunk7UDY4VFQcjs.AuthProvider; exports.AzureProvider = _chunk7UDY4VFQcjs.AzureProvider; exports.ConsentManager = _chunk7UDY4VFQcjs.ConsentManager; exports.DEFAULT_ACCESS_TOKEN_TTL = _chunk7UDY4VFQcjs.DEFAULT_ACCESS_TOKEN_TTL; exports.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH = _chunk7UDY4VFQcjs.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH; exports.DEFAULT_AUTHORIZATION_CODE_TTL = _chunk7UDY4VFQcjs.DEFAULT_AUTHORIZATION_CODE_TTL; exports.DEFAULT_REFRESH_TOKEN_TTL = _chunk7UDY4VFQcjs.DEFAULT_REFRESH_TOKEN_TTL; exports.DEFAULT_TRANSACTION_TTL = _chunk7UDY4VFQcjs.DEFAULT_TRANSACTION_TTL; exports.DiskStore = _chunk7UDY4VFQcjs.DiskStore; exports.EncryptedTokenStorage = _chunk7UDY4VFQcjs.EncryptedTokenStorage; exports.GitHubProvider = _chunk7UDY4VFQcjs.GitHubProvider; exports.GoogleProvider = _chunk7UDY4VFQcjs.GoogleProvider; exports.JWKSVerifier = _chunk7UDY4VFQcjs.JWKSVerifier; exports.JWTIssuer = _chunk7UDY4VFQcjs.JWTIssuer; exports.MemoryTokenStorage = _chunk7UDY4VFQcjs.MemoryTokenStorage; exports.OAuthProvider = _chunk7UDY4VFQcjs.OAuthProvider; exports.OAuthProxy = _chunk7UDY4VFQcjs.OAuthProxy; exports.OAuthProxyError = _chunk7UDY4VFQcjs.OAuthProxyError; exports.PKCEUtils = _chunk7UDY4VFQcjs.PKCEUtils; exports.getAuthSession = _chunk7UDY4VFQcjs.getAuthSession; exports.requireAll = _chunk7UDY4VFQcjs.requireAll; exports.requireAny = _chunk7UDY4VFQcjs.requireAny; exports.requireAuth = _chunk7UDY4VFQcjs.requireAuth; exports.requireRole = _chunk7UDY4VFQcjs.requireRole; exports.requireScopes = _chunk7UDY4VFQcjs.requireScopes;
54
+ exports.AuthProvider = _chunkSSVFQCSNcjs.AuthProvider; exports.AzureProvider = _chunkSSVFQCSNcjs.AzureProvider; exports.ConsentManager = _chunkSSVFQCSNcjs.ConsentManager; exports.DEFAULT_ACCESS_TOKEN_TTL = _chunkSSVFQCSNcjs.DEFAULT_ACCESS_TOKEN_TTL; exports.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH = _chunkSSVFQCSNcjs.DEFAULT_ACCESS_TOKEN_TTL_NO_REFRESH; exports.DEFAULT_AUTHORIZATION_CODE_TTL = _chunkSSVFQCSNcjs.DEFAULT_AUTHORIZATION_CODE_TTL; exports.DEFAULT_REFRESH_TOKEN_TTL = _chunkSSVFQCSNcjs.DEFAULT_REFRESH_TOKEN_TTL; exports.DEFAULT_TRANSACTION_TTL = _chunkSSVFQCSNcjs.DEFAULT_TRANSACTION_TTL; exports.DiskStore = _chunkSSVFQCSNcjs.DiskStore; exports.EncryptedTokenStorage = _chunkSSVFQCSNcjs.EncryptedTokenStorage; exports.GitHubProvider = _chunkSSVFQCSNcjs.GitHubProvider; exports.GoogleProvider = _chunkSSVFQCSNcjs.GoogleProvider; exports.JWKSVerifier = _chunkSSVFQCSNcjs.JWKSVerifier; exports.JWTIssuer = _chunkSSVFQCSNcjs.JWTIssuer; exports.MemoryTokenStorage = _chunkSSVFQCSNcjs.MemoryTokenStorage; exports.OAuthProvider = _chunkSSVFQCSNcjs.OAuthProvider; exports.OAuthProxy = _chunkSSVFQCSNcjs.OAuthProxy; exports.OAuthProxyError = _chunkSSVFQCSNcjs.OAuthProxyError; exports.PKCEUtils = _chunkSSVFQCSNcjs.PKCEUtils; exports.getAuthSession = _chunkSSVFQCSNcjs.getAuthSession; exports.requireAll = _chunkSSVFQCSNcjs.requireAll; exports.requireAny = _chunkSSVFQCSNcjs.requireAny; exports.requireAuth = _chunkSSVFQCSNcjs.requireAuth; exports.requireRole = _chunkSSVFQCSNcjs.requireRole; exports.requireScopes = _chunkSSVFQCSNcjs.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-R8buLRa8.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-R8buLRa8.cjs';
1
+ import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-BV6EpF_k.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-BV6EpF_k.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-R8buLRa8.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-R8buLRa8.js';
1
+ import { p as OAuthTransaction, C as ConsentData, T as TokenStorage, q as TokenVerifier, s as TokenVerificationResult, P as PKCEPair } from '../OAuthProvider-BV6EpF_k.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-BV6EpF_k.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-H4VC4YTC.js";
27
+ } from "../chunk-UN72PIH2.js";
28
28
  export {
29
29
  AuthProvider,
30
30
  AzureProvider,
@@ -863,7 +863,11 @@ var OAuthProxy = (_class4 = class {
863
863
  __init9() {this.transactions = /* @__PURE__ */ new Map()}
864
864
  constructor(config) {;_class4.prototype.__init5.call(this);_class4.prototype.__init6.call(this);_class4.prototype.__init7.call(this);_class4.prototype.__init8.call(this);_class4.prototype.__init9.call(this);
865
865
  this.config = {
866
- allowedRedirectUriPatterns: ["https://*", "http://localhost:*"],
866
+ // Empty by default. Framework users must explicitly configure the URIs they
867
+ // trust, per RFC 6819 §4.1.5. The previous default (`["https://*", "http://localhost:*"]`)
868
+ // allowed open DCR registration of any https URL, enabling CWE-601 open-redirect
869
+ // attacks against /oauth/authorize.
870
+ allowedRedirectUriPatterns: [],
867
871
  authorizationCodeTtl: DEFAULT_AUTHORIZATION_CODE_TTL,
868
872
  consentRequired: true,
869
873
  enableTokenSwap: true,
@@ -913,6 +917,15 @@ var OAuthProxy = (_class4 = class {
913
917
  "Only 'code' response type is supported"
914
918
  );
915
919
  }
920
+ if (params.client_id !== this.config.upstreamClientId) {
921
+ throw new OAuthProxyError("invalid_client", "Unknown client_id");
922
+ }
923
+ if (!this.registeredClients.has(params.redirect_uri)) {
924
+ throw new OAuthProxyError(
925
+ "invalid_request",
926
+ "redirect_uri is not registered for this client"
927
+ );
928
+ }
916
929
  if (params.code_challenge && !params.code_challenge_method) {
917
930
  throw new OAuthProxyError(
918
931
  "invalid_request",
@@ -950,6 +963,9 @@ var OAuthProxy = (_class4 = class {
950
963
  "Only authorization_code grant type is supported"
951
964
  );
952
965
  }
966
+ if (request.client_id !== this.config.upstreamClientId) {
967
+ throw new OAuthProxyError("invalid_client", "Unknown client_id");
968
+ }
953
969
  const clientCode = this.clientCodes.get(request.code);
954
970
  if (!clientCode) {
955
971
  throw new OAuthProxyError(
@@ -1063,6 +1079,13 @@ var OAuthProxy = (_class4 = class {
1063
1079
  if (!transaction) {
1064
1080
  throw new OAuthProxyError("invalid_request", "Invalid or expired state");
1065
1081
  }
1082
+ if (!this.registeredClients.has(transaction.clientCallbackUrl)) {
1083
+ this.transactions.delete(state);
1084
+ throw new OAuthProxyError(
1085
+ "invalid_request",
1086
+ "Transaction callback URL is not registered"
1087
+ );
1088
+ }
1066
1089
  const upstreamTokens = await this.exchangeUpstreamCode(code, transaction);
1067
1090
  const clientCode = this.generateAuthorizationCode(
1068
1091
  transaction,
@@ -1098,6 +1121,12 @@ var OAuthProxy = (_class4 = class {
1098
1121
  }
1099
1122
  if (action === "deny") {
1100
1123
  this.transactions.delete(transactionId);
1124
+ if (!this.registeredClients.has(transaction.clientCallbackUrl)) {
1125
+ throw new OAuthProxyError(
1126
+ "invalid_request",
1127
+ "Transaction callback URL is not registered"
1128
+ );
1129
+ }
1101
1130
  const redirectUrl = new URL(transaction.clientCallbackUrl);
1102
1131
  redirectUrl.searchParams.set("error", "access_denied");
1103
1132
  redirectUrl.searchParams.set(
@@ -1176,7 +1205,9 @@ var OAuthProxy = (_class4 = class {
1176
1205
  },
1177
1206
  registeredAt: /* @__PURE__ */ new Date()
1178
1207
  };
1179
- this.registeredClients.set(request.redirect_uris[0], client);
1208
+ for (const uri of request.redirect_uris) {
1209
+ this.registeredClients.set(uri, client);
1210
+ }
1180
1211
  const response = {
1181
1212
  client_id: clientId,
1182
1213
  client_id_issued_at: Math.floor(Date.now() / 1e3),
@@ -1287,11 +1318,16 @@ var OAuthProxy = (_class4 = class {
1287
1318
  method: "POST"
1288
1319
  });
1289
1320
  if (!tokenResponse.ok) {
1290
- const error = await tokenResponse.json();
1291
- throw new OAuthProxyError(
1292
- error.error || "server_error",
1293
- error.error_description
1294
- );
1321
+ let errorCode = "server_error";
1322
+ let errorDescription;
1323
+ try {
1324
+ const error = await tokenResponse.json();
1325
+ errorCode = error.error || "server_error";
1326
+ errorDescription = error.error_description;
1327
+ } catch (e3) {
1328
+ errorDescription = `Upstream returned HTTP ${tokenResponse.status} ${tokenResponse.statusText}`;
1329
+ }
1330
+ throw new OAuthProxyError(errorCode, errorDescription);
1295
1331
  }
1296
1332
  const tokens = await this.parseTokenResponse(tokenResponse);
1297
1333
  return {
@@ -1425,11 +1461,16 @@ var OAuthProxy = (_class4 = class {
1425
1461
  method: "POST"
1426
1462
  });
1427
1463
  if (!tokenResponse.ok) {
1428
- const error = await tokenResponse.json();
1429
- throw new OAuthProxyError(
1430
- error.error || "invalid_grant",
1431
- error.error_description
1432
- );
1464
+ let errorCode = "invalid_grant";
1465
+ let errorDescription;
1466
+ try {
1467
+ const error = await tokenResponse.json();
1468
+ errorCode = error.error || "invalid_grant";
1469
+ errorDescription = error.error_description;
1470
+ } catch (e4) {
1471
+ errorDescription = `Upstream returned HTTP ${tokenResponse.status} ${tokenResponse.statusText}`;
1472
+ }
1473
+ throw new OAuthProxyError(errorCode, errorDescription);
1433
1474
  }
1434
1475
  const tokens = await this.parseTokenResponse(tokenResponse);
1435
1476
  return {
@@ -1737,11 +1778,16 @@ var OAuthProxy = (_class4 = class {
1737
1778
  method: "POST"
1738
1779
  });
1739
1780
  if (!tokenResponse.ok) {
1740
- const error = await tokenResponse.json();
1741
- throw new OAuthProxyError(
1742
- error.error || "invalid_grant",
1743
- error.error_description || "Upstream refresh failed"
1744
- );
1781
+ let errorCode = "invalid_grant";
1782
+ let errorDescription = "Upstream refresh failed";
1783
+ try {
1784
+ const error = await tokenResponse.json();
1785
+ errorCode = error.error || "invalid_grant";
1786
+ errorDescription = error.error_description || "Upstream refresh failed";
1787
+ } catch (e5) {
1788
+ errorDescription = `Upstream returned HTTP ${tokenResponse.status} ${tokenResponse.statusText}`;
1789
+ }
1790
+ throw new OAuthProxyError(errorCode, errorDescription);
1745
1791
  }
1746
1792
  const tokens = await this.parseTokenResponse(tokenResponse);
1747
1793
  return {
@@ -1764,21 +1810,28 @@ var OAuthProxy = (_class4 = class {
1764
1810
  }, 6e4);
1765
1811
  }
1766
1812
  /**
1767
- * Validate redirect URI against allowed patterns
1813
+ * Validate a redirect URI against the configured allow-list.
1814
+ *
1815
+ * Returns `true` only if the URI is syntactically valid AND matches one of
1816
+ * the explicitly configured `allowedRedirectUriPatterns`. An empty or unset
1817
+ * pattern list means DCR will reject every URI — framework users must
1818
+ * opt-in by listing the exact URIs (or wildcards) they trust.
1819
+ *
1820
+ * Prior versions also fell back to allowing any https URL or localhost,
1821
+ * which enabled attackers to DCR an arbitrary URL and then abuse it via
1822
+ * /oauth/authorize (CWE-601). Do not re-introduce that fallback.
1768
1823
  */
1769
1824
  validateRedirectUri(uri) {
1770
1825
  try {
1771
- const url = new URL(uri);
1772
- const patterns = this.config.allowedRedirectUriPatterns || [];
1773
- for (const pattern of patterns) {
1774
- if (this.matchesPattern(uri, pattern)) {
1775
- return true;
1776
- }
1777
- }
1778
- return url.protocol === "https:" || url.hostname === "localhost" || url.hostname === "127.0.0.1";
1779
- } catch (e3) {
1826
+ new URL(uri);
1827
+ } catch (e6) {
1828
+ return false;
1829
+ }
1830
+ const patterns = this.config.allowedRedirectUriPatterns || [];
1831
+ if (patterns.length === 0) {
1780
1832
  return false;
1781
1833
  }
1834
+ return patterns.some((pattern) => this.matchesPattern(uri, pattern));
1782
1835
  }
1783
1836
  }, _class4);
1784
1837
  var OAuthProxyError = class extends Error {
@@ -1883,10 +1936,10 @@ var AzureProvider = class extends AuthProvider {
1883
1936
  }
1884
1937
  createProxy() {
1885
1938
  return new OAuthProxy({
1886
- allowedRedirectUriPatterns: _nullishCoalesce(this.config.allowedRedirectUriPatterns, () => ( [
1887
- "http://localhost:*",
1888
- "https://*"
1889
- ])),
1939
+ // No fallback default: framework users must explicitly list the URIs
1940
+ // they trust. A previous default of ["http://localhost:*", "https://*"]
1941
+ // enabled CWE-601 open-redirect / code-theft via /oauth/authorize.
1942
+ allowedRedirectUriPatterns: this.config.allowedRedirectUriPatterns,
1890
1943
  baseUrl: this.config.baseUrl,
1891
1944
  consentRequired: _nullishCoalesce(this.config.consentRequired, () => ( true)),
1892
1945
  encryptionKey: this.config.encryptionKey,
@@ -1917,10 +1970,10 @@ var GitHubProvider = class extends AuthProvider {
1917
1970
  }
1918
1971
  createProxy() {
1919
1972
  return new OAuthProxy({
1920
- allowedRedirectUriPatterns: _nullishCoalesce(this.config.allowedRedirectUriPatterns, () => ( [
1921
- "http://localhost:*",
1922
- "https://*"
1923
- ])),
1973
+ // No fallback default: framework users must explicitly list the URIs
1974
+ // they trust. A previous default of ["http://localhost:*", "https://*"]
1975
+ // enabled CWE-601 open-redirect / code-theft via /oauth/authorize.
1976
+ allowedRedirectUriPatterns: this.config.allowedRedirectUriPatterns,
1924
1977
  baseUrl: this.config.baseUrl,
1925
1978
  consentRequired: _nullishCoalesce(this.config.consentRequired, () => ( true)),
1926
1979
  encryptionKey: this.config.encryptionKey,
@@ -1951,10 +2004,10 @@ var GoogleProvider = class extends AuthProvider {
1951
2004
  }
1952
2005
  createProxy() {
1953
2006
  return new OAuthProxy({
1954
- allowedRedirectUriPatterns: _nullishCoalesce(this.config.allowedRedirectUriPatterns, () => ( [
1955
- "http://localhost:*",
1956
- "https://*"
1957
- ])),
2007
+ // No fallback default: framework users must explicitly list the URIs
2008
+ // they trust. A previous default of ["http://localhost:*", "https://*"]
2009
+ // enabled CWE-601 open-redirect / code-theft via /oauth/authorize.
2010
+ allowedRedirectUriPatterns: this.config.allowedRedirectUriPatterns,
1958
2011
  baseUrl: this.config.baseUrl,
1959
2012
  consentRequired: _nullishCoalesce(this.config.consentRequired, () => ( true)),
1960
2013
  encryptionKey: this.config.encryptionKey,
@@ -1987,10 +2040,10 @@ var OAuthProvider = class extends AuthProvider {
1987
2040
  }
1988
2041
  createProxy() {
1989
2042
  return new OAuthProxy({
1990
- allowedRedirectUriPatterns: _nullishCoalesce(this.config.allowedRedirectUriPatterns, () => ( [
1991
- "http://localhost:*",
1992
- "https://*"
1993
- ])),
2043
+ // No fallback default: framework users must explicitly list the URIs
2044
+ // they trust. A previous default of ["http://localhost:*", "https://*"]
2045
+ // enabled CWE-601 open-redirect / code-theft via /oauth/authorize.
2046
+ allowedRedirectUriPatterns: this.config.allowedRedirectUriPatterns,
1994
2047
  baseUrl: this.config.baseUrl,
1995
2048
  consentRequired: _nullishCoalesce(this.config.consentRequired, () => ( true)),
1996
2049
  encryptionKey: this.config.encryptionKey,
@@ -2054,7 +2107,7 @@ var DiskStore = (_class5 = class {
2054
2107
  console.warn(`Failed to read/parse file ${file}, deleting:`, error);
2055
2108
  try {
2056
2109
  await _promises.rm.call(void 0, _path.join.call(void 0, this.directory, file));
2057
- } catch (e4) {
2110
+ } catch (e7) {
2058
2111
  }
2059
2112
  }
2060
2113
  }
@@ -2131,7 +2184,7 @@ var DiskStore = (_class5 = class {
2131
2184
  await this.ensureDirectory();
2132
2185
  const files = await _promises.readdir.call(void 0, this.directory);
2133
2186
  return files.filter((f) => f.endsWith(this.fileExtension)).length;
2134
- } catch (e5) {
2187
+ } catch (e8) {
2135
2188
  return 0;
2136
2189
  }
2137
2190
  }
@@ -2325,4 +2378,4 @@ Original error: ${error.message}`
2325
2378
 
2326
2379
 
2327
2380
  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;
2328
- //# sourceMappingURL=chunk-7UDY4VFQ.cjs.map
2381
+ //# sourceMappingURL=chunk-SSVFQCSN.cjs.map