toolcraft 0.0.313 → 0.0.315
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/composition.json +3 -3
- package/dist/composition.json +3 -3
- package/node_modules/tiny-http-mcp-server/dist/composition.json +1 -1
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/README.md +25 -1
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/auth-store-session-store.d.ts +1 -6
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/auth-store-session-store.js +7 -18
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/client-registration.d.ts +4 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/client-registration.js +103 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +76 -50
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/scope.d.ts +2 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/scope.js +9 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-auth-method.d.ts +2 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-auth-method.js +7 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.d.ts +3 -1
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.js +23 -10
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/types.d.ts +27 -4
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/index.d.ts +2 -1
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/index.js +1 -0
- package/node_modules/tiny-http-mcp-server/package.json +1 -1
- package/node_modules/tiny-mcp-client/dist/index.d.ts +27 -4
- package/node_modules/tiny-mcp-client/dist/index.js +226 -73
- package/node_modules/tiny-stdio-mcp-server/dist/composition.json +1 -1
- package/node_modules/toolcraft-schema/package.json +1 -1
- package/package.json +2 -2
|
@@ -3395,6 +3395,141 @@ var SubscriptionManager = class {
|
|
|
3395
3395
|
}
|
|
3396
3396
|
};
|
|
3397
3397
|
|
|
3398
|
+
// ../mcp-oauth/dist/client/scope.js
|
|
3399
|
+
function normalizeOAuthScope(scope) {
|
|
3400
|
+
if (scope === void 0)
|
|
3401
|
+
return void 0;
|
|
3402
|
+
if (typeof scope !== "string" || [...scope].some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) > 126 || char === '"' || char === "\\"))
|
|
3403
|
+
throw new Error("Invalid OAuth scope syntax");
|
|
3404
|
+
const normalized = [...new Set(scope.split(" ").filter(Boolean))].sort().join(" ");
|
|
3405
|
+
return normalized || void 0;
|
|
3406
|
+
}
|
|
3407
|
+
|
|
3408
|
+
// ../mcp-oauth/dist/client/token-auth-method.js
|
|
3409
|
+
function normalizeOAuthTokenEndpointAuthMethod(value) {
|
|
3410
|
+
if (value === void 0 || value === null)
|
|
3411
|
+
return void 0;
|
|
3412
|
+
if (value !== "none" && value !== "client_secret_post" && value !== "client_secret_basic")
|
|
3413
|
+
throw new Error("Unsupported OAuth token endpoint authentication method");
|
|
3414
|
+
return value;
|
|
3415
|
+
}
|
|
3416
|
+
|
|
3417
|
+
// ../mcp-oauth/dist/client/client-registration.js
|
|
3418
|
+
function parseOAuthClientRegistration(value) {
|
|
3419
|
+
const invalid = () => new Error("Invalid OAuth client registration metadata");
|
|
3420
|
+
let nodes = 0;
|
|
3421
|
+
function copy(input, depth) {
|
|
3422
|
+
if (++nodes > 2e4 || depth > 64)
|
|
3423
|
+
throw invalid();
|
|
3424
|
+
if (input === null || typeof input === "boolean" || typeof input === "string")
|
|
3425
|
+
return input;
|
|
3426
|
+
if (typeof input === "number" && Number.isFinite(input))
|
|
3427
|
+
return input;
|
|
3428
|
+
if (typeof input !== "object" || input === null)
|
|
3429
|
+
throw invalid();
|
|
3430
|
+
const descriptors = Object.getOwnPropertyDescriptors(input);
|
|
3431
|
+
if (Array.isArray(input)) {
|
|
3432
|
+
const length = descriptors.length?.value;
|
|
3433
|
+
if (length > 2e4)
|
|
3434
|
+
throw invalid();
|
|
3435
|
+
const result2 = [];
|
|
3436
|
+
for (let index = 0; index < length; index++) {
|
|
3437
|
+
const descriptor = descriptors[String(index)];
|
|
3438
|
+
if (descriptor === void 0 || !Object.hasOwn(descriptor, "value"))
|
|
3439
|
+
throw invalid();
|
|
3440
|
+
result2.push(copy(descriptor.value, depth + 1));
|
|
3441
|
+
}
|
|
3442
|
+
return result2;
|
|
3443
|
+
}
|
|
3444
|
+
if (Object.getPrototypeOf(input) !== Object.prototype && Object.getPrototypeOf(input) !== null)
|
|
3445
|
+
throw invalid();
|
|
3446
|
+
return Object.fromEntries(Object.entries(descriptors).filter(([, descriptor]) => descriptor.enumerable).map(([key2, descriptor]) => {
|
|
3447
|
+
if (!Object.hasOwn(descriptor, "value"))
|
|
3448
|
+
throw invalid();
|
|
3449
|
+
return [key2, copy(descriptor.value, depth + 1)];
|
|
3450
|
+
}));
|
|
3451
|
+
}
|
|
3452
|
+
let result;
|
|
3453
|
+
try {
|
|
3454
|
+
result = copy(value, 0);
|
|
3455
|
+
} catch {
|
|
3456
|
+
throw invalid();
|
|
3457
|
+
}
|
|
3458
|
+
if (typeof result !== "object" || result === null || Array.isArray(result))
|
|
3459
|
+
throw invalid();
|
|
3460
|
+
const record2 = result;
|
|
3461
|
+
if (!Object.hasOwn(record2, "client_id") || typeof record2.client_id !== "string" || record2.client_id.trim() === "")
|
|
3462
|
+
throw new Error("OAuth client registration response missing client_id");
|
|
3463
|
+
for (const key2 of [
|
|
3464
|
+
"client_id",
|
|
3465
|
+
"client_secret",
|
|
3466
|
+
"token_endpoint_auth_method",
|
|
3467
|
+
"application_type",
|
|
3468
|
+
"client_name",
|
|
3469
|
+
"client_uri",
|
|
3470
|
+
"logo_uri",
|
|
3471
|
+
"scope",
|
|
3472
|
+
"tos_uri",
|
|
3473
|
+
"policy_uri",
|
|
3474
|
+
"jwks_uri",
|
|
3475
|
+
"software_id",
|
|
3476
|
+
"software_version",
|
|
3477
|
+
"software_statement",
|
|
3478
|
+
"registration_access_token",
|
|
3479
|
+
"registration_client_uri",
|
|
3480
|
+
"issuer"
|
|
3481
|
+
]) {
|
|
3482
|
+
if (Object.hasOwn(record2, key2) && record2[key2] !== null && typeof record2[key2] !== "string")
|
|
3483
|
+
throw invalid();
|
|
3484
|
+
}
|
|
3485
|
+
if (typeof record2.client_secret === "string" && record2.client_secret.trim() === "")
|
|
3486
|
+
throw invalid();
|
|
3487
|
+
for (const key2 of ["redirect_uris", "grant_types", "response_types", "contacts"]) {
|
|
3488
|
+
const entry = record2[key2];
|
|
3489
|
+
if (Object.hasOwn(record2, key2) && entry !== null && (!Array.isArray(entry) || entry.some((item) => typeof item !== "string")))
|
|
3490
|
+
throw invalid();
|
|
3491
|
+
}
|
|
3492
|
+
for (const key2 of ["client_id_issued_at", "client_secret_expires_at"]) {
|
|
3493
|
+
const entry = record2[key2];
|
|
3494
|
+
if (Object.hasOwn(record2, key2) && entry !== null && (typeof entry !== "number" || !Number.isSafeInteger(entry) || entry < 0))
|
|
3495
|
+
throw invalid();
|
|
3496
|
+
}
|
|
3497
|
+
try {
|
|
3498
|
+
normalizeOAuthScope(Object.hasOwn(record2, "scope") && record2.scope !== null ? record2.scope : void 0);
|
|
3499
|
+
} catch {
|
|
3500
|
+
throw invalid();
|
|
3501
|
+
}
|
|
3502
|
+
if (Buffer.byteLength(JSON.stringify(record2), "utf8") > 64 * 1024)
|
|
3503
|
+
throw invalid();
|
|
3504
|
+
return record2;
|
|
3505
|
+
}
|
|
3506
|
+
function normalizeStoredOAuthClient(value) {
|
|
3507
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
3508
|
+
return null;
|
|
3509
|
+
const record2 = value;
|
|
3510
|
+
const clientId = Object.hasOwn(record2, "clientId") ? record2.clientId : void 0;
|
|
3511
|
+
const clientSecret = Object.hasOwn(record2, "clientSecret") ? record2.clientSecret : void 0;
|
|
3512
|
+
if (typeof clientId !== "string" || clientId.trim() === "" || clientSecret !== void 0 && (typeof clientSecret !== "string" || clientSecret.trim() === ""))
|
|
3513
|
+
return null;
|
|
3514
|
+
const client = { clientId: clientId.trim(), ...clientSecret === void 0 ? {} : { clientSecret: clientSecret.trim() } };
|
|
3515
|
+
const method = normalizeOAuthTokenEndpointAuthMethod(Object.hasOwn(record2, "tokenEndpointAuthMethod") ? record2.tokenEndpointAuthMethod : void 0);
|
|
3516
|
+
if (Object.hasOwn(record2, "registration") && record2.registration !== void 0) {
|
|
3517
|
+
const registration = parseOAuthClientRegistration(record2.registration);
|
|
3518
|
+
const registeredSecret = Object.hasOwn(registration, "client_secret") ? registration.client_secret?.trim() : void 0;
|
|
3519
|
+
if (registration.client_id.trim() !== client.clientId || registeredSecret !== client.clientSecret)
|
|
3520
|
+
throw new Error("OAuth client registration does not match the client identity");
|
|
3521
|
+
client.registration = registration;
|
|
3522
|
+
const registrationMethod = normalizeOAuthTokenEndpointAuthMethod(Object.hasOwn(registration, "token_endpoint_auth_method") ? registration.token_endpoint_auth_method : void 0);
|
|
3523
|
+
if (method !== void 0 && registrationMethod !== void 0 && method !== registrationMethod)
|
|
3524
|
+
throw new Error("OAuth token endpoint authentication conflicts with the client registration");
|
|
3525
|
+
if (registrationMethod !== void 0)
|
|
3526
|
+
client.tokenEndpointAuthMethod = registrationMethod;
|
|
3527
|
+
}
|
|
3528
|
+
if (method !== void 0)
|
|
3529
|
+
client.tokenEndpointAuthMethod = method;
|
|
3530
|
+
return client;
|
|
3531
|
+
}
|
|
3532
|
+
|
|
3398
3533
|
// ../mcp-oauth/dist/client/auth-store-session-store.js
|
|
3399
3534
|
import crypto from "node:crypto";
|
|
3400
3535
|
import path4 from "node:path";
|
|
@@ -4128,14 +4263,8 @@ function createAuthStoreClientStore(options, namespace) {
|
|
|
4128
4263
|
} catch {
|
|
4129
4264
|
throw new Error("Stored OAuth client must be valid JSON; reset the store explicitly to recover");
|
|
4130
4265
|
}
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
const client = { clientId };
|
|
4134
|
-
if (isObjectRecord(parsed) && Object.prototype.hasOwnProperty.call(parsed, "clientSecret")) {
|
|
4135
|
-
client.clientSecret = getOwnEntry3(parsed, "clientSecret");
|
|
4136
|
-
}
|
|
4137
|
-
return client;
|
|
4138
|
-
}
|
|
4266
|
+
if (isObjectRecord(parsed) && typeof getOwnEntry3(parsed, "clientId") === "string")
|
|
4267
|
+
return parsed;
|
|
4139
4268
|
throw new Error("Stored OAuth client must be a JSON object with clientId");
|
|
4140
4269
|
},
|
|
4141
4270
|
async save(issuer, client) {
|
|
@@ -4201,14 +4330,7 @@ function isStoredOAuthSession(value) {
|
|
|
4201
4330
|
if (!isObjectRecord(value)) {
|
|
4202
4331
|
return false;
|
|
4203
4332
|
}
|
|
4204
|
-
return isNonBlankOwnString(value, "resource") && isNonBlankOwnString(value, "authorizationServer") &&
|
|
4205
|
-
}
|
|
4206
|
-
function isStoredOAuthClient(value) {
|
|
4207
|
-
if (!isObjectRecord(value) || !isNonBlankOwnString(value, "clientId")) {
|
|
4208
|
-
return false;
|
|
4209
|
-
}
|
|
4210
|
-
const clientSecret = getOwnEntry3(value, "clientSecret");
|
|
4211
|
-
return clientSecret === void 0 || typeof clientSecret === "string" && clientSecret.trim().length > 0;
|
|
4333
|
+
return isNonBlankOwnString(value, "resource") && isNonBlankOwnString(value, "authorizationServer") && normalizeStoredOAuthClient(getOwnEntry3(value, "client")) !== null && isStoredOAuthDiscovery(getOwnEntry3(value, "discovery")) && (getOwnEntry3(value, "requestedScope") === void 0 || isNonBlankOwnString(value, "requestedScope")) && (getOwnEntry3(value, "refreshState") === void 0 || getOwnEntry3(value, "refreshState") === "pending" && getOwnEntry3(value, "tokens") === void 0) && isStoredOAuthTokensOrMissing(getOwnEntry3(value, "tokens"));
|
|
4212
4334
|
}
|
|
4213
4335
|
function isStoredOAuthDiscovery(value) {
|
|
4214
4336
|
if (!isObjectRecord(value)) {
|
|
@@ -4655,6 +4777,7 @@ async function exchangeAuthorizationCode(input) {
|
|
|
4655
4777
|
tokenEndpoint: input.tokenEndpoint,
|
|
4656
4778
|
clientId: input.clientId,
|
|
4657
4779
|
clientSecret: input.clientSecret,
|
|
4780
|
+
tokenEndpointAuthMethod: input.tokenEndpointAuthMethod,
|
|
4658
4781
|
params: {
|
|
4659
4782
|
grant_type: "authorization_code",
|
|
4660
4783
|
code: input.code,
|
|
@@ -4673,6 +4796,7 @@ async function refreshAccessToken(input) {
|
|
|
4673
4796
|
tokenEndpoint: input.tokenEndpoint,
|
|
4674
4797
|
clientId: input.clientId,
|
|
4675
4798
|
clientSecret: input.clientSecret,
|
|
4799
|
+
tokenEndpointAuthMethod: input.tokenEndpointAuthMethod,
|
|
4676
4800
|
params: {
|
|
4677
4801
|
grant_type: "refresh_token",
|
|
4678
4802
|
refresh_token: input.refreshToken,
|
|
@@ -4684,21 +4808,26 @@ async function refreshAccessToken(input) {
|
|
|
4684
4808
|
});
|
|
4685
4809
|
}
|
|
4686
4810
|
async function requestTokens(input) {
|
|
4687
|
-
const
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4811
|
+
const method = normalizeOAuthTokenEndpointAuthMethod(input.tokenEndpointAuthMethod) ?? (input.clientSecret === void 0 ? "none" : "client_secret_post");
|
|
4812
|
+
if (method !== "none" && (input.clientSecret === void 0 || input.clientSecret.trim() === ""))
|
|
4813
|
+
throw new Error("OAuth token endpoint authentication requires a client secret");
|
|
4814
|
+
const body = new URLSearchParams(input.params);
|
|
4815
|
+
const headers = new Headers({ "Content-Type": "application/x-www-form-urlencoded" });
|
|
4816
|
+
if (method === "client_secret_basic") {
|
|
4817
|
+
const encoded = new URLSearchParams({ credential: input.clientId }).toString().slice("credential=".length);
|
|
4818
|
+
const encodedSecret = new URLSearchParams({ credential: input.clientSecret }).toString().slice("credential=".length);
|
|
4819
|
+
headers.set("Authorization", `Basic ${Buffer.from(`${encoded}:${encodedSecret}`).toString("base64")}`);
|
|
4820
|
+
} else {
|
|
4821
|
+
body.set("client_id", input.clientId);
|
|
4822
|
+
if (method === "client_secret_post")
|
|
4823
|
+
body.set("client_secret", input.clientSecret);
|
|
4693
4824
|
}
|
|
4694
4825
|
input.signal?.throwIfAborted();
|
|
4695
4826
|
const deadline = AbortSignal.timeout(3e4);
|
|
4696
4827
|
const signal = input.signal === void 0 ? deadline : AbortSignal.any([input.signal, deadline]);
|
|
4697
4828
|
const response = await fetchMcpResponse(input.fetch, input.tokenEndpoint, {
|
|
4698
4829
|
method: "POST",
|
|
4699
|
-
headers
|
|
4700
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
4701
|
-
},
|
|
4830
|
+
headers,
|
|
4702
4831
|
body: body.toString(),
|
|
4703
4832
|
signal
|
|
4704
4833
|
});
|
|
@@ -4726,7 +4855,9 @@ async function requestTokens(input) {
|
|
|
4726
4855
|
const refreshToken = getOwnEntry5(payload, "refresh_token");
|
|
4727
4856
|
const scope = getOwnEntry5(payload, "scope");
|
|
4728
4857
|
const normalizedRefreshToken = typeof refreshToken === "string" && refreshToken.trim().length > 0 ? refreshToken.trim() : void 0;
|
|
4729
|
-
const normalizedScope =
|
|
4858
|
+
const normalizedScope = normalizeOAuthScope(scope);
|
|
4859
|
+
if (scope !== void 0 && normalizedScope === void 0)
|
|
4860
|
+
throw new Error("Invalid OAuth scope syntax in token response");
|
|
4730
4861
|
return {
|
|
4731
4862
|
accessToken: normalizedAccessToken,
|
|
4732
4863
|
refreshToken: normalizedRefreshToken === void 0 ? void 0 : normalizedRefreshToken,
|
|
@@ -4847,6 +4978,11 @@ function createOAuthClientProvider(options) {
|
|
|
4847
4978
|
function createDefaultOAuthClientProvider(options) {
|
|
4848
4979
|
loopbackTarget(options.browser);
|
|
4849
4980
|
assertPersistenceNamespace(options.persistenceNamespace);
|
|
4981
|
+
const clientMetadata = getClientMetadata(options.client);
|
|
4982
|
+
const requestedScope = clientMetadata?.scope;
|
|
4983
|
+
const configuredClient = normalizeConfiguredClient(options.client);
|
|
4984
|
+
const requestedTokenMethod = normalizeOAuthTokenEndpointAuthMethod(options.client.tokenEndpointAuthMethod);
|
|
4985
|
+
const configuredTokenMethod = requestedTokenMethod ?? configuredClient?.tokenEndpointAuthMethod;
|
|
4850
4986
|
const sessionStore = options.sessionStore ?? createAuthStoreSessionStore(options.authStore, options.persistenceNamespace);
|
|
4851
4987
|
const clientStore = options.authStore === void 0 ? null : createAuthStoreClientStore(options.authStore, options.persistenceNamespace);
|
|
4852
4988
|
const now = options.now ?? Date.now;
|
|
@@ -4864,11 +5000,13 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4864
5000
|
const initialGrant = options.initialGrant === void 0 ? void 0 : {
|
|
4865
5001
|
resource: canonicalizeResourceIndicator(options.initialGrant.resource),
|
|
4866
5002
|
tokens: normalizeStoredTokens(options.initialGrant.tokens),
|
|
4867
|
-
client:
|
|
5003
|
+
client: configuredClient
|
|
4868
5004
|
};
|
|
4869
5005
|
if (initialGrant !== void 0 && (initialGrant.tokens === void 0 || initialGrant.client === null))
|
|
4870
5006
|
throw new Error("OAuth initial grant requires valid tokens and the original client ID");
|
|
4871
5007
|
if (initialGrant?.tokens !== void 0) {
|
|
5008
|
+
if (requestedScope !== void 0 && initialGrant.tokens.scope !== requestedScope)
|
|
5009
|
+
throw new Error("OAuth initial grant does not match the requested OAuth scope");
|
|
4872
5010
|
try {
|
|
4873
5011
|
new Headers({ Authorization: `Bearer ${initialGrant.tokens.accessToken}` });
|
|
4874
5012
|
} catch {
|
|
@@ -4956,6 +5094,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4956
5094
|
authorizationServer: discovery.authorizationServer,
|
|
4957
5095
|
client: initialGrant.client,
|
|
4958
5096
|
tokens: initialGrant.tokens,
|
|
5097
|
+
...requestedScope === void 0 ? {} : { requestedScope },
|
|
4959
5098
|
discovery: toStoredDiscovery(discovery)
|
|
4960
5099
|
};
|
|
4961
5100
|
await saveSession(canonicalResource, session);
|
|
@@ -4965,11 +5104,15 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4965
5104
|
if (forceRefresh && rejectedTokens !== void 0 && (rejectedTokens === null || session?.tokens === void 0 || !sameTokenGrant(session.tokens, rejectedTokens)))
|
|
4966
5105
|
forceRefresh = false;
|
|
4967
5106
|
const sessionDiscovery = resolveDiscovery(discovery, session);
|
|
4968
|
-
if ((options.client.mode === "static" || initialGrant !== void 0) && session !== null && (session.tokens !== void 0 || session.refreshState === "pending")) {
|
|
4969
|
-
const configured =
|
|
5107
|
+
if ((options.client.mode === "static" || configuredClient?.registration !== void 0 || initialGrant !== void 0) && session !== null && (session.tokens !== void 0 || session.refreshState === "pending")) {
|
|
5108
|
+
const configured = configuredClient;
|
|
4970
5109
|
if (configured === null || configured.clientId !== session.client.clientId || configured.clientSecret !== session.client.clientSecret)
|
|
4971
5110
|
throw new Error("Stored session belongs to a different OAuth client; use separate persistence or explicitly reset it");
|
|
4972
5111
|
}
|
|
5112
|
+
if (requestedScope !== void 0 && session?.tokens !== void 0 && normalizeOAuthScope(session.tokens.scope ?? session.requestedScope) !== requestedScope)
|
|
5113
|
+
throw new Error("Stored session does not match the requested OAuth scope; authorize again or select separate persistence");
|
|
5114
|
+
if (configuredTokenMethod !== void 0 && session !== null && (session.tokens !== void 0 || session.refreshState === "pending") && (session.client.tokenEndpointAuthMethod ?? (session.client.clientSecret === void 0 ? "none" : "client_secret_post")) !== configuredTokenMethod)
|
|
5115
|
+
throw new Error("Stored session does not match the requested OAuth token endpoint authentication; select separate persistence or reset it");
|
|
4973
5116
|
if (session?.refreshState === "pending") {
|
|
4974
5117
|
if (!allowInteractive || options.allowInteractive === false || sessionDiscovery === void 0)
|
|
4975
5118
|
throw new Error("OAuth refresh outcome is unknown; authorize again before using this resource");
|
|
@@ -5002,6 +5145,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5002
5145
|
if (session.tokens?.refreshToken === void 0) {
|
|
5003
5146
|
return session;
|
|
5004
5147
|
}
|
|
5148
|
+
assertTokenEndpointAuthentication(session.client, discovery.authorizationServerMetadata);
|
|
5005
5149
|
const pendingSession = { ...clearSessionTokens(session), refreshState: "pending" };
|
|
5006
5150
|
await saveSession(resource, pendingSession);
|
|
5007
5151
|
signal?.throwIfAborted();
|
|
@@ -5013,6 +5157,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5013
5157
|
tokenEndpoint: requireOwnString(discovery.authorizationServerMetadata, "token_endpoint", "Authorization server metadata"),
|
|
5014
5158
|
clientId: session.client.clientId,
|
|
5015
5159
|
clientSecret: session.client.clientSecret,
|
|
5160
|
+
tokenEndpointAuthMethod: session.client.tokenEndpointAuthMethod,
|
|
5016
5161
|
refreshToken: session.tokens.refreshToken,
|
|
5017
5162
|
resource,
|
|
5018
5163
|
fetch: fetch2,
|
|
@@ -5046,10 +5191,13 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5046
5191
|
...session,
|
|
5047
5192
|
tokens: {
|
|
5048
5193
|
...refreshedTokens,
|
|
5049
|
-
refreshToken: refreshedTokens.refreshToken ?? session.tokens.refreshToken
|
|
5194
|
+
refreshToken: refreshedTokens.refreshToken ?? session.tokens.refreshToken,
|
|
5195
|
+
scope: refreshedTokens.scope ?? session.tokens.scope
|
|
5050
5196
|
},
|
|
5051
5197
|
discovery: toStoredDiscovery(discovery)
|
|
5052
5198
|
};
|
|
5199
|
+
if (requestedScope !== void 0 && normalizeOAuthScope(updatedSession.tokens?.scope ?? session.requestedScope) !== requestedScope)
|
|
5200
|
+
throw new Error("OAuth refresh response does not match the requested OAuth scope; authorize again");
|
|
5053
5201
|
await saveSession(resource, updatedSession);
|
|
5054
5202
|
return updatedSession;
|
|
5055
5203
|
}
|
|
@@ -5073,10 +5221,12 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5073
5221
|
let resolvedClient = null;
|
|
5074
5222
|
try {
|
|
5075
5223
|
resolvedClient = await resolveClient(currentSession, discovery, loopback.redirectUri, fetch2, signal);
|
|
5224
|
+
assertTokenEndpointAuthentication(resolvedClient.client, discovery.authorizationServerMetadata);
|
|
5076
5225
|
const sessionWithoutTokens = {
|
|
5077
5226
|
resource,
|
|
5078
5227
|
authorizationServer: discovery.authorizationServer,
|
|
5079
5228
|
client: resolvedClient.client,
|
|
5229
|
+
...requestedScope === void 0 ? {} : { requestedScope },
|
|
5080
5230
|
discovery: toStoredDiscovery(discovery)
|
|
5081
5231
|
};
|
|
5082
5232
|
await saveSession(resource, sessionWithoutTokens);
|
|
@@ -5088,13 +5238,14 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5088
5238
|
clientId: resolvedClient.client.clientId,
|
|
5089
5239
|
redirectUri: loopback.redirectUri,
|
|
5090
5240
|
codeChallenge: challenge,
|
|
5091
|
-
clientMetadata
|
|
5241
|
+
clientMetadata
|
|
5092
5242
|
});
|
|
5093
5243
|
const code = await loopback.waitForCode(authorizationUrl);
|
|
5094
5244
|
const tokens = await exchangeAuthorizationCode({
|
|
5095
5245
|
tokenEndpoint: requireOwnString(discovery.authorizationServerMetadata, "token_endpoint", "Authorization server metadata"),
|
|
5096
5246
|
clientId: resolvedClient.client.clientId,
|
|
5097
5247
|
clientSecret: resolvedClient.client.clientSecret,
|
|
5248
|
+
tokenEndpointAuthMethod: resolvedClient.client.tokenEndpointAuthMethod,
|
|
5098
5249
|
code,
|
|
5099
5250
|
codeVerifier: verifier,
|
|
5100
5251
|
redirectUri: loopback.redirectUri,
|
|
@@ -5103,6 +5254,8 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5103
5254
|
signal,
|
|
5104
5255
|
now
|
|
5105
5256
|
});
|
|
5257
|
+
if (requestedScope !== void 0 && tokens.scope !== void 0 && normalizeOAuthScope(tokens.scope) !== requestedScope)
|
|
5258
|
+
throw new Error("OAuth authorization response does not match the requested OAuth scope");
|
|
5106
5259
|
const session = {
|
|
5107
5260
|
...sessionWithoutTokens,
|
|
5108
5261
|
tokens
|
|
@@ -5132,8 +5285,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5132
5285
|
}
|
|
5133
5286
|
async function resolveClient(existingSession, discovery, redirectUri, fetch2, parentSignal) {
|
|
5134
5287
|
parentSignal?.throwIfAborted();
|
|
5135
|
-
|
|
5136
|
-
if (options.client.mode === "static") {
|
|
5288
|
+
if (options.client.mode === "static" || configuredClient?.registration !== void 0) {
|
|
5137
5289
|
if (configuredClient === null) {
|
|
5138
5290
|
throw new Error("OAuth client_id must not be blank");
|
|
5139
5291
|
}
|
|
@@ -5180,7 +5332,11 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5180
5332
|
};
|
|
5181
5333
|
}
|
|
5182
5334
|
}
|
|
5183
|
-
const
|
|
5335
|
+
const supported = getSupportedTokenAuthMethods(discovery.authorizationServerMetadata);
|
|
5336
|
+
const registrationMethod = requestedTokenMethod ?? (supported === void 0 ? "none" : ["none", "client_secret_basic", "client_secret_post"].find((method) => supported.includes(method)));
|
|
5337
|
+
if (registrationMethod === void 0 || supported !== void 0 && !supported.includes(registrationMethod))
|
|
5338
|
+
throw new Error("Authorization server does not support the requested OAuth token endpoint authentication");
|
|
5339
|
+
const registrationBody = buildClientRegistrationBody(clientMetadata, redirectUri, registrationMethod);
|
|
5184
5340
|
const deadline = AbortSignal.timeout(3e4);
|
|
5185
5341
|
const signal = parentSignal === void 0 ? deadline : AbortSignal.any([parentSignal, deadline]);
|
|
5186
5342
|
const response = await fetchMcpResponse(fetch2, registrationEndpoint, {
|
|
@@ -5192,14 +5348,14 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5192
5348
|
signal
|
|
5193
5349
|
});
|
|
5194
5350
|
const payload = await readOAuthJsonObjectResponse(response, signal);
|
|
5195
|
-
const
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
}
|
|
5199
|
-
const clientSecret = getOwnString2(payload, "client_secret");
|
|
5351
|
+
const registration = parseOAuthClientRegistration(payload);
|
|
5352
|
+
const registeredSecret = getOwnString2(registration, "client_secret");
|
|
5353
|
+
const responseMethod = normalizeOAuthTokenEndpointAuthMethod(getOwnEntry6(registration, "token_endpoint_auth_method")) ?? requestedTokenMethod ?? (supported === void 0 ? void 0 : normalizeOAuthTokenEndpointAuthMethod(registrationMethod));
|
|
5200
5354
|
const registeredClient = {
|
|
5201
|
-
clientId:
|
|
5202
|
-
|
|
5355
|
+
clientId: registration.client_id.trim(),
|
|
5356
|
+
...registeredSecret === void 0 ? {} : { clientSecret: registeredSecret.trim() },
|
|
5357
|
+
...responseMethod === void 0 ? {} : { tokenEndpointAuthMethod: responseMethod },
|
|
5358
|
+
registration
|
|
5203
5359
|
};
|
|
5204
5360
|
await saveRegisteredClient(discovery.authorizationServer, registeredClient);
|
|
5205
5361
|
return {
|
|
@@ -5212,7 +5368,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5212
5368
|
return normalizeLoadedSession(await sessionStore.load(resource));
|
|
5213
5369
|
}
|
|
5214
5370
|
async function saveSession(resource, session) {
|
|
5215
|
-
await sessionStore.save(resource, session);
|
|
5371
|
+
await sessionStore.save(resource, structuredClone(session));
|
|
5216
5372
|
}
|
|
5217
5373
|
async function clearSession(resource) {
|
|
5218
5374
|
await sessionStore.clear(resource);
|
|
@@ -5225,7 +5381,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5225
5381
|
return null;
|
|
5226
5382
|
}
|
|
5227
5383
|
const client = await clientStore.load(issuer);
|
|
5228
|
-
const normalizedClient = client === null ? null :
|
|
5384
|
+
const normalizedClient = client === null ? null : normalizeStoredOAuthClient(client);
|
|
5229
5385
|
if (client !== null && normalizedClient === null) {
|
|
5230
5386
|
await clientStore.clear(issuer);
|
|
5231
5387
|
return null;
|
|
@@ -5298,7 +5454,7 @@ function normalizeLoadedSession(session) {
|
|
|
5298
5454
|
const refreshState = getOwnEntry6(session, "refreshState");
|
|
5299
5455
|
if (refreshState !== void 0 && (refreshState !== "pending" || getOwnEntry6(session, "tokens") !== void 0))
|
|
5300
5456
|
throw new Error("Stored OAuth refresh state is invalid");
|
|
5301
|
-
const client =
|
|
5457
|
+
const client = normalizeStoredOAuthClient(getOwnEntry6(session, "client"));
|
|
5302
5458
|
if (client === null) {
|
|
5303
5459
|
return { ...session, client: { clientId: "" }, tokens: void 0 };
|
|
5304
5460
|
}
|
|
@@ -5308,25 +5464,6 @@ function normalizeLoadedSession(session) {
|
|
|
5308
5464
|
tokens: normalizeStoredTokens(getOwnEntry6(session, "tokens"))
|
|
5309
5465
|
};
|
|
5310
5466
|
}
|
|
5311
|
-
function normalizeStoredClient(value) {
|
|
5312
|
-
if (!isObjectRecord3(value)) {
|
|
5313
|
-
return null;
|
|
5314
|
-
}
|
|
5315
|
-
const clientId = getOwnString2(value, "clientId");
|
|
5316
|
-
if (clientId === void 0 || clientId.trim().length === 0) {
|
|
5317
|
-
return null;
|
|
5318
|
-
}
|
|
5319
|
-
const normalizedClientId = clientId.trim();
|
|
5320
|
-
const clientSecret = getOwnEntry6(value, "clientSecret");
|
|
5321
|
-
if (clientSecret === void 0) {
|
|
5322
|
-
return { clientId: normalizedClientId };
|
|
5323
|
-
}
|
|
5324
|
-
if (typeof clientSecret !== "string" || clientSecret.trim().length === 0) {
|
|
5325
|
-
return null;
|
|
5326
|
-
}
|
|
5327
|
-
const normalizedClientSecret = clientSecret.trim();
|
|
5328
|
-
return { clientId: normalizedClientId, clientSecret: normalizedClientSecret };
|
|
5329
|
-
}
|
|
5330
5467
|
function normalizeStoredTokens(value) {
|
|
5331
5468
|
if (value === void 0 || !isObjectRecord3(value)) {
|
|
5332
5469
|
return void 0;
|
|
@@ -5335,10 +5472,10 @@ function normalizeStoredTokens(value) {
|
|
|
5335
5472
|
const tokenType = getOwnString2(value, "tokenType");
|
|
5336
5473
|
const expiresAt = getOwnEntry6(value, "expiresAt");
|
|
5337
5474
|
const refreshToken = getOwnEntry6(value, "refreshToken");
|
|
5338
|
-
const scope =
|
|
5475
|
+
const scope = getOwnEntry6(value, "scope");
|
|
5339
5476
|
const normalizedAccessToken = accessToken?.trim();
|
|
5340
5477
|
const normalizedRefreshToken = typeof refreshToken === "string" ? refreshToken.trim() : void 0;
|
|
5341
|
-
const normalizedScope = scope
|
|
5478
|
+
const normalizedScope = normalizeOAuthScope(scope);
|
|
5342
5479
|
if (accessToken === void 0 || normalizedAccessToken === void 0 || normalizedAccessToken.length === 0 || tokenType !== "Bearer" || !(expiresAt === null || typeof expiresAt === "number" && Number.isSafeInteger(expiresAt) && expiresAt <= MAX_JS_DATE_MS3 && Number.isFinite(new Date(expiresAt).getTime())) || refreshToken !== void 0 && (typeof refreshToken !== "string" || normalizedRefreshToken === void 0 || normalizedRefreshToken.length === 0)) {
|
|
5343
5480
|
return void 0;
|
|
5344
5481
|
}
|
|
@@ -5356,18 +5493,18 @@ function getClientMetadata(client) {
|
|
|
5356
5493
|
}
|
|
5357
5494
|
return {
|
|
5358
5495
|
clientName: normalizeOptionalOAuthString(client.metadata.clientName),
|
|
5359
|
-
scope:
|
|
5496
|
+
scope: normalizeOAuthScope(client.metadata.scope),
|
|
5360
5497
|
softwareId: normalizeOptionalOAuthString(client.metadata.softwareId),
|
|
5361
5498
|
softwareVersion: normalizeOptionalOAuthString(client.metadata.softwareVersion)
|
|
5362
5499
|
};
|
|
5363
5500
|
}
|
|
5364
5501
|
function normalizeConfiguredClient(client) {
|
|
5365
|
-
const
|
|
5366
|
-
|
|
5502
|
+
const registration = client.registration === void 0 ? void 0 : parseOAuthClientRegistration(client.registration);
|
|
5503
|
+
const clientId = normalizeOptionalOAuthString(client.clientId) ?? registration?.client_id.trim();
|
|
5504
|
+
if (clientId === void 0)
|
|
5367
5505
|
return null;
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
return clientSecret === void 0 ? { clientId } : { clientId, clientSecret };
|
|
5506
|
+
const clientSecret = normalizeOptionalOAuthString(client.clientSecret) ?? (registration === void 0 ? void 0 : getOwnString2(registration, "client_secret")?.trim());
|
|
5507
|
+
return normalizeStoredOAuthClient({ clientId, clientSecret, registration, tokenEndpointAuthMethod: client.tokenEndpointAuthMethod });
|
|
5371
5508
|
}
|
|
5372
5509
|
function normalizeOptionalOAuthString(value) {
|
|
5373
5510
|
if (value === void 0) {
|
|
@@ -5467,12 +5604,28 @@ function assertRequestMatchesResource(requestUrl, resource) {
|
|
|
5467
5604
|
throw new Error(`OAuth request URL ${requestUrl} does not match discovered resource ${resource}`);
|
|
5468
5605
|
}
|
|
5469
5606
|
}
|
|
5470
|
-
function
|
|
5607
|
+
function getSupportedTokenAuthMethods(metadata) {
|
|
5608
|
+
const value = getOwnEntry6(metadata, "token_endpoint_auth_methods_supported");
|
|
5609
|
+
if (value === void 0)
|
|
5610
|
+
return void 0;
|
|
5611
|
+
if (!Array.isArray(value) || value.length > 128 || value.some((method) => typeof method !== "string"))
|
|
5612
|
+
throw new Error("Invalid OAuth token endpoint authentication metadata");
|
|
5613
|
+
return value;
|
|
5614
|
+
}
|
|
5615
|
+
function assertTokenEndpointAuthentication(client, metadata) {
|
|
5616
|
+
const method = client.tokenEndpointAuthMethod ?? (client.clientSecret === void 0 ? "none" : "client_secret_post");
|
|
5617
|
+
if (method !== "none" && client.clientSecret === void 0)
|
|
5618
|
+
throw new Error("OAuth token endpoint authentication requires a client secret");
|
|
5619
|
+
const supported = getSupportedTokenAuthMethods(metadata);
|
|
5620
|
+
if (supported !== void 0 && !supported.includes(method))
|
|
5621
|
+
throw new Error("Authorization server does not support the requested OAuth token endpoint authentication");
|
|
5622
|
+
}
|
|
5623
|
+
function buildClientRegistrationBody(metadata, redirectUri, tokenEndpointAuthMethod) {
|
|
5471
5624
|
const body = {
|
|
5472
5625
|
redirect_uris: [redirectUri],
|
|
5473
5626
|
grant_types: ["authorization_code", "refresh_token"],
|
|
5474
5627
|
response_types: ["code"],
|
|
5475
|
-
token_endpoint_auth_method:
|
|
5628
|
+
token_endpoint_auth_method: tokenEndpointAuthMethod
|
|
5476
5629
|
};
|
|
5477
5630
|
const clientName = metadata === void 0 ? void 0 : getOwnString2(metadata, "clientName");
|
|
5478
5631
|
const scope = metadata === void 0 ? void 0 : getOwnString2(metadata, "scope");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolcraft",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.315",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
"yaml"
|
|
159
159
|
],
|
|
160
160
|
"optionalDependencies": {
|
|
161
|
-
"toolcraft-schema": "0.0.
|
|
161
|
+
"toolcraft-schema": "0.0.315",
|
|
162
162
|
"toolcraft-design": "*",
|
|
163
163
|
"@poe-code/frontmatter": "*",
|
|
164
164
|
"@poe-code/agent-mcp-config": "*",
|