fastmcp 3.35.0 → 4.0.1
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 +3 -3
- package/dist/FastMCP.d.cts +2 -2
- package/dist/FastMCP.d.ts +2 -2
- package/dist/FastMCP.js +2 -2
- package/dist/{OAuthProvider-R8buLRa8.d.cts → OAuthProvider-BV6EpF_k.d.cts} +38 -3
- package/dist/{OAuthProvider-R8buLRa8.d.ts → OAuthProvider-BV6EpF_k.d.ts} +38 -3
- package/dist/auth/index.cjs +2 -2
- package/dist/auth/index.d.cts +2 -2
- package/dist/auth/index.d.ts +2 -2
- package/dist/auth/index.js +1 -1
- package/dist/{chunk-JP7QSER3.cjs → chunk-EXZZ3NKL.cjs} +102 -89
- package/dist/chunk-EXZZ3NKL.cjs.map +1 -0
- package/dist/{chunk-7UDY4VFQ.cjs → chunk-SSVFQCSN.cjs} +99 -46
- package/dist/chunk-SSVFQCSN.cjs.map +1 -0
- package/dist/{chunk-UVX47AE5.js → chunk-TNX4H4LB.js} +102 -89
- package/dist/{chunk-UVX47AE5.js.map → chunk-TNX4H4LB.js.map} +1 -1
- package/dist/{chunk-H4VC4YTC.js → chunk-UN72PIH2.js} +96 -43
- package/dist/chunk-UN72PIH2.js.map +1 -0
- package/dist/examples/custom-routes.cjs +3 -3
- package/dist/examples/custom-routes.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-7UDY4VFQ.cjs.map +0 -1
- package/dist/chunk-H4VC4YTC.js.map +0 -1
- package/dist/chunk-JP7QSER3.cjs.map +0 -1
|
@@ -863,7 +863,11 @@ var OAuthProxy = class {
|
|
|
863
863
|
transactions = /* @__PURE__ */ new Map();
|
|
864
864
|
constructor(config) {
|
|
865
865
|
this.config = {
|
|
866
|
-
|
|
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 = 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 = 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 = 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 = 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 = class {
|
|
|
1176
1205
|
},
|
|
1177
1206
|
registeredAt: /* @__PURE__ */ new Date()
|
|
1178
1207
|
};
|
|
1179
|
-
|
|
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 = class {
|
|
|
1287
1318
|
method: "POST"
|
|
1288
1319
|
});
|
|
1289
1320
|
if (!tokenResponse.ok) {
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
error.
|
|
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 {
|
|
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 = class {
|
|
|
1425
1461
|
method: "POST"
|
|
1426
1462
|
});
|
|
1427
1463
|
if (!tokenResponse.ok) {
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
error.
|
|
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 {
|
|
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 = class {
|
|
|
1737
1778
|
method: "POST"
|
|
1738
1779
|
});
|
|
1739
1780
|
if (!tokenResponse.ok) {
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
error
|
|
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 {
|
|
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 = class {
|
|
|
1764
1810
|
}, 6e4);
|
|
1765
1811
|
}
|
|
1766
1812
|
/**
|
|
1767
|
-
* Validate redirect URI against
|
|
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
|
-
|
|
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";
|
|
1826
|
+
new URL(uri);
|
|
1779
1827
|
} catch {
|
|
1780
1828
|
return false;
|
|
1781
1829
|
}
|
|
1830
|
+
const patterns = this.config.allowedRedirectUriPatterns || [];
|
|
1831
|
+
if (patterns.length === 0) {
|
|
1832
|
+
return false;
|
|
1833
|
+
}
|
|
1834
|
+
return patterns.some((pattern) => this.matchesPattern(uri, pattern));
|
|
1782
1835
|
}
|
|
1783
1836
|
};
|
|
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
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
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: 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
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
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: 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
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
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: 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
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
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: this.config.consentRequired ?? true,
|
|
1996
2049
|
encryptionKey: this.config.encryptionKey,
|
|
@@ -2325,4 +2378,4 @@ export {
|
|
|
2325
2378
|
DiskStore,
|
|
2326
2379
|
JWKSVerifier
|
|
2327
2380
|
};
|
|
2328
|
-
//# sourceMappingURL=chunk-
|
|
2381
|
+
//# sourceMappingURL=chunk-UN72PIH2.js.map
|