@ai-sdk/mcp 0.0.41 → 0.0.43
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/CHANGELOG.md +22 -0
- package/dist/index.d.mts +50 -2
- package/dist/index.d.ts +50 -2
- package/dist/index.js +360 -45
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +360 -45
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -301,15 +301,6 @@ var import_pkce_challenge = __toESM(require("pkce-challenge"));
|
|
|
301
301
|
|
|
302
302
|
// src/tool/oauth-types.ts
|
|
303
303
|
var import_v43 = require("zod/v4");
|
|
304
|
-
var OAuthTokensSchema = import_v43.z.object({
|
|
305
|
-
access_token: import_v43.z.string(),
|
|
306
|
-
id_token: import_v43.z.string().optional(),
|
|
307
|
-
// Optional for OAuth 2.1, but necessary in OpenID Connect
|
|
308
|
-
token_type: import_v43.z.string(),
|
|
309
|
-
expires_in: import_v43.z.number().optional(),
|
|
310
|
-
scope: import_v43.z.string().optional(),
|
|
311
|
-
refresh_token: import_v43.z.string().optional()
|
|
312
|
-
}).strip();
|
|
313
304
|
var SafeUrlSchema = import_v43.z.string().url().superRefine((val, ctx) => {
|
|
314
305
|
if (!URL.canParse(val)) {
|
|
315
306
|
ctx.addIssue({
|
|
@@ -326,6 +317,18 @@ var SafeUrlSchema = import_v43.z.string().url().superRefine((val, ctx) => {
|
|
|
326
317
|
},
|
|
327
318
|
{ message: "URL cannot use javascript:, data:, or vbscript: scheme" }
|
|
328
319
|
);
|
|
320
|
+
var OAuthTokensSchema = import_v43.z.object({
|
|
321
|
+
access_token: import_v43.z.string(),
|
|
322
|
+
id_token: import_v43.z.string().optional(),
|
|
323
|
+
// Optional for OAuth 2.1, but necessary in OpenID Connect
|
|
324
|
+
token_type: import_v43.z.string(),
|
|
325
|
+
expires_in: import_v43.z.number().optional(),
|
|
326
|
+
scope: import_v43.z.string().optional(),
|
|
327
|
+
refresh_token: import_v43.z.string().optional(),
|
|
328
|
+
issuer: SafeUrlSchema.optional(),
|
|
329
|
+
authorization_server: SafeUrlSchema.optional(),
|
|
330
|
+
token_endpoint: SafeUrlSchema.optional()
|
|
331
|
+
}).strip();
|
|
329
332
|
var OAuthProtectedResourceMetadataSchema = import_v43.z.object({
|
|
330
333
|
resource: import_v43.z.string().url(),
|
|
331
334
|
authorization_servers: import_v43.z.array(SafeUrlSchema).optional(),
|
|
@@ -378,7 +381,10 @@ var OAuthClientInformationSchema = import_v43.z.object({
|
|
|
378
381
|
client_id: import_v43.z.string(),
|
|
379
382
|
client_secret: import_v43.z.string().optional(),
|
|
380
383
|
client_id_issued_at: import_v43.z.number().optional(),
|
|
381
|
-
client_secret_expires_at: import_v43.z.number().optional()
|
|
384
|
+
client_secret_expires_at: import_v43.z.number().optional(),
|
|
385
|
+
issuer: SafeUrlSchema.optional(),
|
|
386
|
+
authorization_server: SafeUrlSchema.optional(),
|
|
387
|
+
token_endpoint: SafeUrlSchema.optional()
|
|
382
388
|
}).strip();
|
|
383
389
|
var OAuthClientMetadataSchema = import_v43.z.object({
|
|
384
390
|
redirect_uris: import_v43.z.array(SafeUrlSchema),
|
|
@@ -476,6 +482,130 @@ var UnauthorizedError = class extends Error {
|
|
|
476
482
|
this.name = "UnauthorizedError";
|
|
477
483
|
}
|
|
478
484
|
};
|
|
485
|
+
function normalizeUrl(url) {
|
|
486
|
+
return new URL(url).href;
|
|
487
|
+
}
|
|
488
|
+
function validateAuthorizationResponseIssuer({
|
|
489
|
+
callbackIssuer,
|
|
490
|
+
expectedIssuer
|
|
491
|
+
}) {
|
|
492
|
+
if (callbackIssuer != null && callbackIssuer !== expectedIssuer) {
|
|
493
|
+
throw new MCPClientOAuthError({
|
|
494
|
+
message: `OAuth authorization response issuer ${callbackIssuer} does not match expected issuer ${expectedIssuer}`
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
function createAuthorizationServerInformation(authorizationServerUrl, metadata) {
|
|
499
|
+
var _a3;
|
|
500
|
+
return {
|
|
501
|
+
issuer: (_a3 = metadata == null ? void 0 : metadata.issuer) != null ? _a3 : String(authorizationServerUrl),
|
|
502
|
+
authorizationServerUrl: normalizeUrl(authorizationServerUrl),
|
|
503
|
+
tokenEndpoint: normalizeUrl(
|
|
504
|
+
(metadata == null ? void 0 : metadata.token_endpoint) ? new URL(metadata.token_endpoint) : new URL("/token", authorizationServerUrl)
|
|
505
|
+
)
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function addAuthorizationServerInformationToTokens(tokens, authorizationServerInformation) {
|
|
509
|
+
return {
|
|
510
|
+
...tokens,
|
|
511
|
+
issuer: authorizationServerInformation.issuer,
|
|
512
|
+
authorization_server: authorizationServerInformation.authorizationServerUrl,
|
|
513
|
+
token_endpoint: authorizationServerInformation.tokenEndpoint
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
function addAuthorizationServerInformationToClientInformation(clientInformation, authorizationServerInformation) {
|
|
517
|
+
return {
|
|
518
|
+
...clientInformation,
|
|
519
|
+
issuer: authorizationServerInformation.issuer,
|
|
520
|
+
authorization_server: authorizationServerInformation.authorizationServerUrl,
|
|
521
|
+
token_endpoint: authorizationServerInformation.tokenEndpoint
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
function getAuthorizationServerInformationFromCredentials(credentials) {
|
|
525
|
+
if (!(credentials == null ? void 0 : credentials.authorization_server) || !credentials.token_endpoint) {
|
|
526
|
+
return void 0;
|
|
527
|
+
}
|
|
528
|
+
return {
|
|
529
|
+
issuer: credentials.issuer,
|
|
530
|
+
authorizationServerUrl: normalizeUrl(credentials.authorization_server),
|
|
531
|
+
tokenEndpoint: normalizeUrl(credentials.token_endpoint)
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
async function getStoredAuthorizationServerInformation({
|
|
535
|
+
provider,
|
|
536
|
+
clientInformation,
|
|
537
|
+
tokens
|
|
538
|
+
}) {
|
|
539
|
+
var _a3;
|
|
540
|
+
const tokenAuthorizationServerInformation = getAuthorizationServerInformationFromCredentials(tokens);
|
|
541
|
+
if (tokenAuthorizationServerInformation) {
|
|
542
|
+
return tokenAuthorizationServerInformation;
|
|
543
|
+
}
|
|
544
|
+
const providerAuthorizationServerInformation = await ((_a3 = provider.authorizationServerInformation) == null ? void 0 : _a3.call(provider));
|
|
545
|
+
if (providerAuthorizationServerInformation) {
|
|
546
|
+
return {
|
|
547
|
+
issuer: providerAuthorizationServerInformation.issuer,
|
|
548
|
+
authorizationServerUrl: normalizeUrl(
|
|
549
|
+
providerAuthorizationServerInformation.authorizationServerUrl
|
|
550
|
+
),
|
|
551
|
+
tokenEndpoint: normalizeUrl(
|
|
552
|
+
providerAuthorizationServerInformation.tokenEndpoint
|
|
553
|
+
)
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
return getAuthorizationServerInformationFromCredentials(clientInformation);
|
|
557
|
+
}
|
|
558
|
+
async function saveAuthorizationServerInformation({
|
|
559
|
+
provider,
|
|
560
|
+
clientInformation,
|
|
561
|
+
authorizationServerInformation
|
|
562
|
+
}) {
|
|
563
|
+
if (provider.saveAuthorizationServerInformation) {
|
|
564
|
+
await provider.saveAuthorizationServerInformation(
|
|
565
|
+
authorizationServerInformation
|
|
566
|
+
);
|
|
567
|
+
return true;
|
|
568
|
+
}
|
|
569
|
+
if (provider.saveClientInformation) {
|
|
570
|
+
await provider.saveClientInformation(
|
|
571
|
+
addAuthorizationServerInformationToClientInformation(
|
|
572
|
+
clientInformation,
|
|
573
|
+
authorizationServerInformation
|
|
574
|
+
)
|
|
575
|
+
);
|
|
576
|
+
return true;
|
|
577
|
+
}
|
|
578
|
+
const configuredBinding = getAuthorizationServerInformationFromCredentials(clientInformation);
|
|
579
|
+
if (configuredBinding) {
|
|
580
|
+
assertAuthorizationServerInformationMatches({
|
|
581
|
+
storedAuthorizationServerInformation: configuredBinding,
|
|
582
|
+
currentAuthorizationServerInformation: authorizationServerInformation
|
|
583
|
+
});
|
|
584
|
+
return true;
|
|
585
|
+
}
|
|
586
|
+
return false;
|
|
587
|
+
}
|
|
588
|
+
function assertResourceMetadataUrlSameOrigin(serverUrl, resourceMetadataUrl) {
|
|
589
|
+
if (!resourceMetadataUrl) {
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
const expectedOrigin = new URL(serverUrl).origin;
|
|
593
|
+
if (resourceMetadataUrl.origin !== expectedOrigin) {
|
|
594
|
+
throw new MCPClientOAuthError({
|
|
595
|
+
message: `OAuth protected resource metadata URL ${resourceMetadataUrl.href} must have the same origin as the MCP server URL ${expectedOrigin}`
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
function assertAuthorizationServerInformationMatches({
|
|
600
|
+
storedAuthorizationServerInformation,
|
|
601
|
+
currentAuthorizationServerInformation
|
|
602
|
+
}) {
|
|
603
|
+
if (storedAuthorizationServerInformation.issuer != null && currentAuthorizationServerInformation.issuer != null && storedAuthorizationServerInformation.issuer !== currentAuthorizationServerInformation.issuer || storedAuthorizationServerInformation.authorizationServerUrl !== currentAuthorizationServerInformation.authorizationServerUrl || storedAuthorizationServerInformation.tokenEndpoint !== currentAuthorizationServerInformation.tokenEndpoint) {
|
|
604
|
+
throw new MCPClientOAuthError({
|
|
605
|
+
message: "OAuth authorization server metadata does not match the metadata that issued the stored credentials"
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
}
|
|
479
609
|
function extractResourceMetadataUrl(response) {
|
|
480
610
|
var _a3;
|
|
481
611
|
const header = (_a3 = response.headers.get("www-authenticate")) != null ? _a3 : response.headers.get("WWW-Authenticate");
|
|
@@ -618,15 +748,18 @@ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn =
|
|
|
618
748
|
function buildDiscoveryUrls(authorizationServerUrl) {
|
|
619
749
|
const url = typeof authorizationServerUrl === "string" ? new URL(authorizationServerUrl) : authorizationServerUrl;
|
|
620
750
|
const hasPath = url.pathname !== "/";
|
|
751
|
+
const rootIssuer = url.origin;
|
|
621
752
|
const urlsToTry = [];
|
|
622
753
|
if (!hasPath) {
|
|
623
754
|
urlsToTry.push({
|
|
624
755
|
url: new URL("/.well-known/oauth-authorization-server", url.origin),
|
|
625
|
-
type: "oauth"
|
|
756
|
+
type: "oauth",
|
|
757
|
+
expectedIssuer: rootIssuer
|
|
626
758
|
});
|
|
627
759
|
urlsToTry.push({
|
|
628
760
|
url: new URL("/.well-known/openid-configuration", url.origin),
|
|
629
|
-
type: "oidc"
|
|
761
|
+
type: "oidc",
|
|
762
|
+
expectedIssuer: rootIssuer
|
|
630
763
|
});
|
|
631
764
|
return urlsToTry;
|
|
632
765
|
}
|
|
@@ -634,27 +767,42 @@ function buildDiscoveryUrls(authorizationServerUrl) {
|
|
|
634
767
|
if (pathname.endsWith("/")) {
|
|
635
768
|
pathname = pathname.slice(0, -1);
|
|
636
769
|
}
|
|
770
|
+
const pathIssuer = `${url.origin}${pathname}`;
|
|
637
771
|
urlsToTry.push({
|
|
638
772
|
url: new URL(
|
|
639
773
|
`/.well-known/oauth-authorization-server${pathname}`,
|
|
640
774
|
url.origin
|
|
641
775
|
),
|
|
642
|
-
type: "oauth"
|
|
776
|
+
type: "oauth",
|
|
777
|
+
expectedIssuer: pathIssuer
|
|
643
778
|
});
|
|
644
779
|
urlsToTry.push({
|
|
645
780
|
url: new URL("/.well-known/oauth-authorization-server", url.origin),
|
|
646
|
-
type: "oauth"
|
|
781
|
+
type: "oauth",
|
|
782
|
+
expectedIssuer: rootIssuer
|
|
647
783
|
});
|
|
648
784
|
urlsToTry.push({
|
|
649
785
|
url: new URL(`/.well-known/openid-configuration${pathname}`, url.origin),
|
|
650
|
-
type: "oidc"
|
|
786
|
+
type: "oidc",
|
|
787
|
+
expectedIssuer: pathIssuer
|
|
651
788
|
});
|
|
789
|
+
const oidcDiscoveryUrl = new URL(url.origin);
|
|
790
|
+
oidcDiscoveryUrl.pathname = `${pathname}/.well-known/openid-configuration`;
|
|
652
791
|
urlsToTry.push({
|
|
653
|
-
url:
|
|
654
|
-
type: "oidc"
|
|
792
|
+
url: oidcDiscoveryUrl,
|
|
793
|
+
type: "oidc",
|
|
794
|
+
expectedIssuer: pathIssuer
|
|
655
795
|
});
|
|
656
796
|
return urlsToTry;
|
|
657
797
|
}
|
|
798
|
+
function assertMetadataIssuerMatches(metadata, expectedIssuer) {
|
|
799
|
+
const issuerMatches = metadata.issuer === expectedIssuer || expectedIssuer === new URL(expectedIssuer).origin && metadata.issuer === `${expectedIssuer}/`;
|
|
800
|
+
if (!issuerMatches) {
|
|
801
|
+
throw new MCPClientOAuthError({
|
|
802
|
+
message: `OAuth authorization server metadata issuer ${metadata.issuer} does not match expected issuer ${expectedIssuer}`
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
}
|
|
658
806
|
async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
|
|
659
807
|
fetchFn = fetch,
|
|
660
808
|
protocolVersion = LATEST_PROTOCOL_VERSION,
|
|
@@ -662,8 +810,14 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
|
|
|
662
810
|
} = {}) {
|
|
663
811
|
var _a3;
|
|
664
812
|
const headers = { "MCP-Protocol-Version": protocolVersion };
|
|
813
|
+
const authorizationServerOrigin = new URL(authorizationServerUrl).origin;
|
|
665
814
|
const urlsToTry = buildDiscoveryUrls(authorizationServerUrl);
|
|
666
|
-
|
|
815
|
+
if (urlsToTry.some(({ url }) => url.origin !== authorizationServerOrigin)) {
|
|
816
|
+
throw new MCPClientOAuthError({
|
|
817
|
+
message: "OAuth discovery URL changed authorization-server origin"
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
for (const { url: endpointUrl, type, expectedIssuer } of urlsToTry) {
|
|
667
821
|
const response = await fetchWithCorsRetry(
|
|
668
822
|
endpointUrl,
|
|
669
823
|
headers,
|
|
@@ -682,11 +836,14 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
|
|
|
682
836
|
);
|
|
683
837
|
}
|
|
684
838
|
if (type === "oauth") {
|
|
685
|
-
|
|
839
|
+
const metadata = OAuthMetadataSchema.parse(await response.json());
|
|
840
|
+
assertMetadataIssuerMatches(metadata, expectedIssuer);
|
|
841
|
+
return metadata;
|
|
686
842
|
} else {
|
|
687
843
|
const metadata = OpenIdProviderDiscoveryMetadataSchema.parse(
|
|
688
844
|
await response.json()
|
|
689
845
|
);
|
|
846
|
+
assertMetadataIssuerMatches(metadata, expectedIssuer);
|
|
690
847
|
if (!((_a3 = metadata.code_challenge_methods_supported) == null ? void 0 : _a3.includes("S256"))) {
|
|
691
848
|
throw new Error(
|
|
692
849
|
`Incompatible OIDC provider at ${endpointUrl}: does not support S256 code challenge method required by MCP specification`
|
|
@@ -695,7 +852,6 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, {
|
|
|
695
852
|
return metadata;
|
|
696
853
|
}
|
|
697
854
|
}
|
|
698
|
-
return void 0;
|
|
699
855
|
}
|
|
700
856
|
async function startAuthorization(authorizationServerUrl, {
|
|
701
857
|
metadata,
|
|
@@ -977,16 +1133,28 @@ async function registerClient(authorizationServerUrl, {
|
|
|
977
1133
|
return OAuthClientInformationFullSchema.parse(await response.json());
|
|
978
1134
|
}
|
|
979
1135
|
async function auth(provider, options) {
|
|
980
|
-
var _a3, _b3;
|
|
1136
|
+
var _a3, _b3, _c;
|
|
1137
|
+
const refreshAttempt = {};
|
|
981
1138
|
try {
|
|
982
|
-
return await authInternal(provider, options);
|
|
1139
|
+
return await authInternal(provider, options, refreshAttempt);
|
|
983
1140
|
} catch (error) {
|
|
984
1141
|
if (error instanceof InvalidClientError || error instanceof UnauthorizedClientError) {
|
|
985
|
-
await ((_a3 = provider.
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
await ((_b3 = provider.invalidateCredentials) == null ? void 0 : _b3.call(provider, "
|
|
1142
|
+
if (options.authorizationCode !== void 0 || !await ((_a3 = provider.isClientInformationDynamicallyRegistered) == null ? void 0 : _a3.call(provider))) {
|
|
1143
|
+
throw error;
|
|
1144
|
+
}
|
|
1145
|
+
await ((_b3 = provider.invalidateCredentials) == null ? void 0 : _b3.call(provider, "all"));
|
|
989
1146
|
return await authInternal(provider, options);
|
|
1147
|
+
} else if (error instanceof InvalidGrantError && refreshAttempt.tokens) {
|
|
1148
|
+
const retryAuthorizationServerInformation = getAuthorizationServerInformationFromCredentials(refreshAttempt.tokens);
|
|
1149
|
+
await ((_c = provider.invalidateCredentials) == null ? void 0 : _c.call(provider, "tokens", {
|
|
1150
|
+
tokens: refreshAttempt.tokens
|
|
1151
|
+
}));
|
|
1152
|
+
return await authInternal(
|
|
1153
|
+
provider,
|
|
1154
|
+
options,
|
|
1155
|
+
void 0,
|
|
1156
|
+
retryAuthorizationServerInformation
|
|
1157
|
+
);
|
|
990
1158
|
}
|
|
991
1159
|
throw error;
|
|
992
1160
|
}
|
|
@@ -1015,12 +1183,18 @@ async function selectResourceURL(serverUrl, provider, resourceMetadata) {
|
|
|
1015
1183
|
async function authInternal(provider, {
|
|
1016
1184
|
serverUrl,
|
|
1017
1185
|
authorizationCode,
|
|
1186
|
+
callbackState,
|
|
1187
|
+
callbackIssuer,
|
|
1018
1188
|
scope,
|
|
1019
1189
|
resourceMetadataUrl,
|
|
1020
1190
|
fetchFn
|
|
1021
|
-
}) {
|
|
1191
|
+
}, refreshAttempt, retryAuthorizationServerInformation) {
|
|
1192
|
+
var _a3, _b3, _c, _d, _e, _f;
|
|
1022
1193
|
let resourceMetadata;
|
|
1023
1194
|
let authorizationServerUrl;
|
|
1195
|
+
let clientInformation;
|
|
1196
|
+
let callbackAuthorizationServerInformation;
|
|
1197
|
+
assertResourceMetadataUrlSameOrigin(serverUrl, resourceMetadataUrl);
|
|
1024
1198
|
try {
|
|
1025
1199
|
resourceMetadata = await discoverOAuthProtectedResourceMetadata(
|
|
1026
1200
|
serverUrl,
|
|
@@ -1032,8 +1206,17 @@ async function authInternal(provider, {
|
|
|
1032
1206
|
}
|
|
1033
1207
|
} catch (e) {
|
|
1034
1208
|
}
|
|
1209
|
+
if (authorizationCode !== void 0) {
|
|
1210
|
+
clientInformation = await Promise.resolve(provider.clientInformation());
|
|
1211
|
+
if (clientInformation) {
|
|
1212
|
+
callbackAuthorizationServerInformation = await getStoredAuthorizationServerInformation({
|
|
1213
|
+
provider,
|
|
1214
|
+
clientInformation
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1035
1218
|
if (!authorizationServerUrl) {
|
|
1036
|
-
authorizationServerUrl = serverUrl;
|
|
1219
|
+
authorizationServerUrl = (_a3 = callbackAuthorizationServerInformation == null ? void 0 : callbackAuthorizationServerInformation.authorizationServerUrl) != null ? _a3 : serverUrl;
|
|
1037
1220
|
}
|
|
1038
1221
|
const parsedServerUrl = new URL(serverUrl);
|
|
1039
1222
|
const parsedAuthorizationServerUrl = new URL(authorizationServerUrl);
|
|
@@ -1048,6 +1231,11 @@ async function authInternal(provider, {
|
|
|
1048
1231
|
provider,
|
|
1049
1232
|
resourceMetadata
|
|
1050
1233
|
);
|
|
1234
|
+
await ((_b3 = provider.validateAuthorizationServerURL) == null ? void 0 : _b3.call(
|
|
1235
|
+
provider,
|
|
1236
|
+
serverUrl,
|
|
1237
|
+
authorizationServerUrl
|
|
1238
|
+
));
|
|
1051
1239
|
const metadata = await discoverAuthorizationServerMetadata(
|
|
1052
1240
|
authorizationServerUrl,
|
|
1053
1241
|
{
|
|
@@ -1055,7 +1243,59 @@ async function authInternal(provider, {
|
|
|
1055
1243
|
trustedOrigin: trustedAuthorizationServerOrigin
|
|
1056
1244
|
}
|
|
1057
1245
|
);
|
|
1058
|
-
|
|
1246
|
+
const currentAuthorizationServerInformation = createAuthorizationServerInformation(authorizationServerUrl, metadata);
|
|
1247
|
+
if (retryAuthorizationServerInformation) {
|
|
1248
|
+
assertAuthorizationServerInformationMatches({
|
|
1249
|
+
storedAuthorizationServerInformation: retryAuthorizationServerInformation,
|
|
1250
|
+
currentAuthorizationServerInformation
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1253
|
+
const clientMetadata = provider.clientMetadata;
|
|
1254
|
+
if (authorizationCode === void 0) {
|
|
1255
|
+
clientInformation = await Promise.resolve(provider.clientInformation());
|
|
1256
|
+
}
|
|
1257
|
+
let tokens = authorizationCode === void 0 ? await provider.tokens() : void 0;
|
|
1258
|
+
if (clientInformation) {
|
|
1259
|
+
if (clientInformation.issuer != null && clientInformation.issuer !== currentAuthorizationServerInformation.issuer) {
|
|
1260
|
+
throw new MCPClientOAuthError({
|
|
1261
|
+
message: "OAuth authorization server does not match the issuer of the client credentials"
|
|
1262
|
+
});
|
|
1263
|
+
}
|
|
1264
|
+
const clientAuthorizationServerInformation = getAuthorizationServerInformationFromCredentials(clientInformation);
|
|
1265
|
+
if (clientAuthorizationServerInformation) {
|
|
1266
|
+
assertAuthorizationServerInformationMatches({
|
|
1267
|
+
storedAuthorizationServerInformation: clientAuthorizationServerInformation,
|
|
1268
|
+
currentAuthorizationServerInformation
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
const storedAuthorizationServerInformation = (_c = callbackAuthorizationServerInformation != null ? callbackAuthorizationServerInformation : await getStoredAuthorizationServerInformation({
|
|
1272
|
+
provider,
|
|
1273
|
+
clientInformation,
|
|
1274
|
+
tokens
|
|
1275
|
+
})) != null ? _c : retryAuthorizationServerInformation;
|
|
1276
|
+
if (storedAuthorizationServerInformation) {
|
|
1277
|
+
assertAuthorizationServerInformationMatches({
|
|
1278
|
+
storedAuthorizationServerInformation,
|
|
1279
|
+
currentAuthorizationServerInformation
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
if ((clientInformation.client_secret != null || provider.addClientAuthentication) && clientInformation.issuer == null && !storedAuthorizationServerInformation) {
|
|
1283
|
+
if (authorizationCode === void 0 && await ((_d = provider.isClientInformationDynamicallyRegistered) == null ? void 0 : _d.call(provider))) {
|
|
1284
|
+
if (!provider.invalidateCredentials) {
|
|
1285
|
+
throw new MCPClientOAuthError({
|
|
1286
|
+
message: "invalidateCredentials is required to discard unbound legacy OAuth credentials; clear stored credentials before authorizing again"
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
await provider.invalidateCredentials("all");
|
|
1290
|
+
clientInformation = void 0;
|
|
1291
|
+
tokens = void 0;
|
|
1292
|
+
} else {
|
|
1293
|
+
throw new MCPClientOAuthError({
|
|
1294
|
+
message: "OAuth client credentials must be bound to an authorization server: configure their issuer or store authorization server information"
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1059
1299
|
if (!clientInformation) {
|
|
1060
1300
|
if (authorizationCode !== void 0) {
|
|
1061
1301
|
throw new Error(
|
|
@@ -1069,13 +1309,41 @@ async function authInternal(provider, {
|
|
|
1069
1309
|
}
|
|
1070
1310
|
const fullInformation = await registerClient(authorizationServerUrl, {
|
|
1071
1311
|
metadata,
|
|
1072
|
-
clientMetadata
|
|
1312
|
+
clientMetadata,
|
|
1073
1313
|
fetchFn
|
|
1074
1314
|
});
|
|
1075
|
-
|
|
1076
|
-
|
|
1315
|
+
clientInformation = addAuthorizationServerInformationToClientInformation(
|
|
1316
|
+
fullInformation,
|
|
1317
|
+
currentAuthorizationServerInformation
|
|
1318
|
+
);
|
|
1319
|
+
await provider.saveClientInformation(clientInformation);
|
|
1077
1320
|
}
|
|
1078
1321
|
if (authorizationCode !== void 0) {
|
|
1322
|
+
if (provider.storedState) {
|
|
1323
|
+
const expectedState = await provider.storedState();
|
|
1324
|
+
if (expectedState !== void 0 && expectedState !== callbackState) {
|
|
1325
|
+
throw new Error(
|
|
1326
|
+
"OAuth state parameter mismatch - possible CSRF attack"
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
const storedAuthorizationServerInformation = callbackAuthorizationServerInformation != null ? callbackAuthorizationServerInformation : await getStoredAuthorizationServerInformation({
|
|
1331
|
+
provider,
|
|
1332
|
+
clientInformation
|
|
1333
|
+
});
|
|
1334
|
+
if (!storedAuthorizationServerInformation) {
|
|
1335
|
+
throw new MCPClientOAuthError({
|
|
1336
|
+
message: "Stored OAuth authorization server metadata is required when exchanging an authorization code"
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1339
|
+
validateAuthorizationResponseIssuer({
|
|
1340
|
+
callbackIssuer,
|
|
1341
|
+
expectedIssuer: (_f = (_e = storedAuthorizationServerInformation.issuer) != null ? _e : metadata == null ? void 0 : metadata.issuer) != null ? _f : String(authorizationServerUrl)
|
|
1342
|
+
});
|
|
1343
|
+
assertAuthorizationServerInformationMatches({
|
|
1344
|
+
storedAuthorizationServerInformation,
|
|
1345
|
+
currentAuthorizationServerInformation
|
|
1346
|
+
});
|
|
1079
1347
|
const codeVerifier2 = await provider.codeVerifier();
|
|
1080
1348
|
const tokens2 = await exchangeAuthorization(authorizationServerUrl, {
|
|
1081
1349
|
metadata,
|
|
@@ -1087,22 +1355,56 @@ async function authInternal(provider, {
|
|
|
1087
1355
|
addClientAuthentication: provider.addClientAuthentication,
|
|
1088
1356
|
fetchFn
|
|
1089
1357
|
});
|
|
1090
|
-
await provider.saveTokens(
|
|
1358
|
+
await provider.saveTokens(
|
|
1359
|
+
addAuthorizationServerInformationToTokens(
|
|
1360
|
+
tokens2,
|
|
1361
|
+
currentAuthorizationServerInformation
|
|
1362
|
+
)
|
|
1363
|
+
);
|
|
1091
1364
|
return "AUTHORIZED";
|
|
1092
1365
|
}
|
|
1093
|
-
const tokens = await provider.tokens();
|
|
1094
1366
|
if (tokens == null ? void 0 : tokens.refresh_token) {
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1367
|
+
const storedAuthorizationServerInformation = await getStoredAuthorizationServerInformation({
|
|
1368
|
+
provider,
|
|
1369
|
+
clientInformation,
|
|
1370
|
+
tokens
|
|
1371
|
+
});
|
|
1372
|
+
if (storedAuthorizationServerInformation) {
|
|
1373
|
+
assertAuthorizationServerInformationMatches({
|
|
1374
|
+
storedAuthorizationServerInformation,
|
|
1375
|
+
currentAuthorizationServerInformation
|
|
1103
1376
|
});
|
|
1104
|
-
|
|
1105
|
-
|
|
1377
|
+
} else {
|
|
1378
|
+
if (!provider.invalidateCredentials) {
|
|
1379
|
+
throw new MCPClientOAuthError({
|
|
1380
|
+
message: "invalidateCredentials is required to discard unbound legacy OAuth tokens; clear stored tokens before authorizing again"
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
await provider.invalidateCredentials("tokens", {
|
|
1384
|
+
tokens: { ...tokens }
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
1387
|
+
try {
|
|
1388
|
+
if (storedAuthorizationServerInformation) {
|
|
1389
|
+
if (refreshAttempt) {
|
|
1390
|
+
refreshAttempt.tokens = { ...tokens };
|
|
1391
|
+
}
|
|
1392
|
+
const newTokens = await refreshAuthorization(authorizationServerUrl, {
|
|
1393
|
+
metadata,
|
|
1394
|
+
clientInformation,
|
|
1395
|
+
refreshToken: tokens.refresh_token,
|
|
1396
|
+
resource,
|
|
1397
|
+
addClientAuthentication: provider.addClientAuthentication,
|
|
1398
|
+
fetchFn
|
|
1399
|
+
});
|
|
1400
|
+
await provider.saveTokens(
|
|
1401
|
+
addAuthorizationServerInformationToTokens(
|
|
1402
|
+
newTokens,
|
|
1403
|
+
currentAuthorizationServerInformation
|
|
1404
|
+
)
|
|
1405
|
+
);
|
|
1406
|
+
return "AUTHORIZED";
|
|
1407
|
+
}
|
|
1106
1408
|
} catch (error) {
|
|
1107
1409
|
if (
|
|
1108
1410
|
// If this is a ServerError, or an unknown type, log it out and try to continue. Otherwise, escalate so we can fix things and retry.
|
|
@@ -1114,6 +1416,9 @@ async function authInternal(provider, {
|
|
|
1114
1416
|
}
|
|
1115
1417
|
}
|
|
1116
1418
|
const state = provider.state ? await provider.state() : void 0;
|
|
1419
|
+
if (state && provider.saveState) {
|
|
1420
|
+
await provider.saveState(state);
|
|
1421
|
+
}
|
|
1117
1422
|
const { authorizationUrl, codeVerifier } = await startAuthorization(
|
|
1118
1423
|
authorizationServerUrl,
|
|
1119
1424
|
{
|
|
@@ -1121,10 +1426,20 @@ async function authInternal(provider, {
|
|
|
1121
1426
|
clientInformation,
|
|
1122
1427
|
state,
|
|
1123
1428
|
redirectUrl: provider.redirectUrl,
|
|
1124
|
-
scope: scope ||
|
|
1429
|
+
scope: scope || clientMetadata.scope,
|
|
1125
1430
|
resource
|
|
1126
1431
|
}
|
|
1127
1432
|
);
|
|
1433
|
+
const savedAuthorizationServerInformation = await saveAuthorizationServerInformation({
|
|
1434
|
+
provider,
|
|
1435
|
+
clientInformation,
|
|
1436
|
+
authorizationServerInformation: currentAuthorizationServerInformation
|
|
1437
|
+
});
|
|
1438
|
+
if (!savedAuthorizationServerInformation) {
|
|
1439
|
+
throw new MCPClientOAuthError({
|
|
1440
|
+
message: "OAuth authorization server metadata must be saveable before starting authorization"
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1128
1443
|
await provider.saveCodeVerifier(codeVerifier);
|
|
1129
1444
|
await provider.redirectToAuthorization(authorizationUrl);
|
|
1130
1445
|
return "REDIRECT";
|