tiny-http-mcp-server 0.1.36 → 0.1.38
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/composition.json +1 -1
- package/node_modules/mcp-oauth/README.md +9 -0
- package/node_modules/mcp-oauth/dist/client/auth-store-session-store.d.ts +9 -2
- package/node_modules/mcp-oauth/dist/client/auth-store-session-store.js +2 -2
- package/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +13 -2
- package/node_modules/mcp-oauth/dist/client/resource-bound-store.d.ts +9 -0
- package/node_modules/mcp-oauth/dist/client/resource-bound-store.js +118 -0
- package/node_modules/mcp-oauth/dist/client/types.d.ts +2 -0
- package/node_modules/tiny-mcp-client/dist/index.d.ts +2 -0
- package/node_modules/tiny-mcp-client/dist/index.js +124 -2
- package/package.json +1 -1
package/dist/composition.json
CHANGED
|
@@ -102,6 +102,15 @@ normalized. An imported grant must declare its scope when a scope is configured.
|
|
|
102
102
|
Authorization records the requested set when the endpoint omits scope, and
|
|
103
103
|
refresh retains the previous granted set. Mismatched responses never activate
|
|
104
104
|
credentials; an unusable refresh response retains the pending refresh record.
|
|
105
|
+
`resourceIdentity` selects a native-owned logical server within its optional
|
|
106
|
+
persistence namespace. One encrypted, locked document owns that identity's
|
|
107
|
+
current resource URL, sessions and registrations. Changing the URL retires its
|
|
108
|
+
credentials permanently; returning to the old URL does not restore them.
|
|
109
|
+
Retired identities also withhold stale initial grants; authorize again or select
|
|
110
|
+
a fresh explicit profile to import a new grant. This option requires native persistence; custom
|
|
111
|
+
session stores own their durable resource trust policy. Without it, the native
|
|
112
|
+
client retains its existing resource-URL cache behavior.
|
|
113
|
+
|
|
105
114
|
Select a separate persistence namespace for another scope profile. No scope is
|
|
106
115
|
invented when the client does not configure one.
|
|
107
116
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type CreateSecretStoreInput } from "auth-store";
|
|
2
|
-
import type { OAuthSessionStore, StoredOAuthClient } from "./types.js";
|
|
1
|
+
import { type CreateSecretStoreInput, type SecretStore } from "auth-store";
|
|
2
|
+
import type { OAuthSessionStore, StoredOAuthSession, StoredOAuthClient } from "./types.js";
|
|
3
3
|
export interface OAuthClientStore {
|
|
4
4
|
load(issuer: string): Promise<StoredOAuthClient | null>;
|
|
5
5
|
save(issuer: string, client: StoredOAuthClient): Promise<void>;
|
|
@@ -7,4 +7,11 @@ export interface OAuthClientStore {
|
|
|
7
7
|
}
|
|
8
8
|
export declare function createAuthStoreSessionStore(options?: CreateSecretStoreInput, namespace?: string): OAuthSessionStore;
|
|
9
9
|
export declare function createAuthStoreClientStore(options: CreateSecretStoreInput, namespace?: string): OAuthClientStore;
|
|
10
|
+
export declare function createNamedSecretStore(key: string, options: CreateSecretStoreInput, defaults: {
|
|
11
|
+
salt: string;
|
|
12
|
+
directory: string;
|
|
13
|
+
service: string;
|
|
14
|
+
accountPrefix: string;
|
|
15
|
+
}, namespace?: string): SecretStore;
|
|
10
16
|
export declare function assertPersistenceNamespace(namespace: string | undefined): void;
|
|
17
|
+
export declare function isStoredOAuthSession(value: unknown): value is StoredOAuthSession;
|
|
@@ -79,7 +79,7 @@ export function createAuthStoreClientStore(options, namespace) {
|
|
|
79
79
|
}
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
-
function createNamedSecretStore(key, options, defaults, namespace) {
|
|
82
|
+
export function createNamedSecretStore(key, options, defaults, namespace) {
|
|
83
83
|
const hash = crypto.createHash("sha256").update(namespace === undefined ? key : JSON.stringify([namespace, key])).digest("hex");
|
|
84
84
|
const configuredFilePath = options.fileStore?.filePath;
|
|
85
85
|
const parsedFilePath = configuredFilePath === undefined ? null : path.parse(configuredFilePath);
|
|
@@ -132,7 +132,7 @@ function getOwnString(record, key) {
|
|
|
132
132
|
const value = getOwnEntry(record, key);
|
|
133
133
|
return typeof value === "string" ? value : undefined;
|
|
134
134
|
}
|
|
135
|
-
function isStoredOAuthSession(value) {
|
|
135
|
+
export function isStoredOAuthSession(value) {
|
|
136
136
|
if (!isObjectRecord(value)) {
|
|
137
137
|
return false;
|
|
138
138
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createResourceBoundOAuthStores } from "./resource-bound-store.js";
|
|
1
2
|
import { normalizeStoredOAuthClient, parseOAuthClientRegistration, registrationMatchesRedirect } from "./client-registration.js";
|
|
2
3
|
import { normalizeOAuthScope } from "./scope.js";
|
|
3
4
|
import { normalizeOAuthTokenEndpointAuthMethod } from "./token-auth-method.js";
|
|
@@ -26,8 +27,13 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
26
27
|
const configuredClient = normalizeConfiguredClient(options.client);
|
|
27
28
|
const requestedTokenMethod = normalizeOAuthTokenEndpointAuthMethod(options.client.tokenEndpointAuthMethod);
|
|
28
29
|
const configuredTokenMethod = requestedTokenMethod ?? configuredClient?.tokenEndpointAuthMethod;
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
if (options.resourceIdentity !== undefined && options.sessionStore !== undefined)
|
|
31
|
+
throw new Error("OAuth resourceIdentity requires native-owned persistence; custom stores own their resource trust policy");
|
|
32
|
+
const resourceStores = options.resourceIdentity === undefined ? undefined :
|
|
33
|
+
createResourceBoundOAuthStores(options.authStore ?? {}, options.persistenceNamespace, options.resourceIdentity);
|
|
34
|
+
const sessionStore = resourceStores?.sessionStore ?? options.sessionStore ?? createAuthStoreSessionStore(options.authStore, options.persistenceNamespace);
|
|
35
|
+
const clientStore = resourceStores?.clientStore ??
|
|
36
|
+
(options.authStore === undefined ? null : createAuthStoreClientStore(options.authStore, options.persistenceNamespace));
|
|
31
37
|
const now = options.now ?? Date.now;
|
|
32
38
|
const registeredClients = new Map();
|
|
33
39
|
if (options.initialGrant !== undefined) {
|
|
@@ -127,6 +133,11 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
127
133
|
const canonicalResource = canonicalizeResourceIndicator(resource);
|
|
128
134
|
return withOAuthSessionTransaction(sessionStore, canonicalResource, async () => {
|
|
129
135
|
let session = await loadSession(canonicalResource);
|
|
136
|
+
if (resourceStores !== undefined) {
|
|
137
|
+
registeredClients.clear();
|
|
138
|
+
if (!resourceStores.initialGrantAllowed)
|
|
139
|
+
initialGrantConsumed = true;
|
|
140
|
+
}
|
|
130
141
|
if (session !== null)
|
|
131
142
|
assertRegistrationIssuer(session.client, session.authorizationServer);
|
|
132
143
|
if (configuredClient !== null && discovery !== undefined)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CreateSecretStoreInput } from "auth-store";
|
|
2
|
+
import { type OAuthClientStore } from "./auth-store-session-store.js";
|
|
3
|
+
import type { OAuthSessionStore } from "./types.js";
|
|
4
|
+
/** One locked document owns a logical server's URL history, grant and clients. */
|
|
5
|
+
export declare function createResourceBoundOAuthStores(options: CreateSecretStoreInput, namespace: string | undefined, identity: string): {
|
|
6
|
+
sessionStore: OAuthSessionStore;
|
|
7
|
+
clientStore: OAuthClientStore;
|
|
8
|
+
initialGrantAllowed: boolean;
|
|
9
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { canonicalizeResourceIndicator } from "../resource-indicator.js";
|
|
2
|
+
import { assertPersistenceNamespace, createNamedSecretStore, isStoredOAuthSession } from "./auth-store-session-store.js";
|
|
3
|
+
import { normalizeStoredOAuthClient } from "./client-registration.js";
|
|
4
|
+
/** One locked document owns a logical server's URL history, grant and clients. */
|
|
5
|
+
export function createResourceBoundOAuthStores(options, namespace, identity) {
|
|
6
|
+
assertPersistenceNamespace(identity);
|
|
7
|
+
const store = createNamedSecretStore(identity, options, { salt: "poe-code:mcp-oauth:resources:v1",
|
|
8
|
+
directory: ".poe-code/mcp-oauth/resources", service: "poe-code-mcp-oauth-resources", accountPrefix: "resource" }, namespace);
|
|
9
|
+
const result = { initialGrantAllowed: true, sessionStore: {}, clientStore: {} };
|
|
10
|
+
async function read() {
|
|
11
|
+
const raw = await store.get();
|
|
12
|
+
if (raw === null)
|
|
13
|
+
return null;
|
|
14
|
+
let value;
|
|
15
|
+
try {
|
|
16
|
+
value = JSON.parse(raw);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
throw new Error("Stored OAuth resource identity must be valid JSON; reset explicitly to recover");
|
|
20
|
+
}
|
|
21
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
22
|
+
throw new Error("Invalid stored OAuth resource identity");
|
|
23
|
+
const record = value;
|
|
24
|
+
if (!["version", "resource", "generation", "session", "clients"].every(key => Object.hasOwn(record, key)) || record.version !== 1 || typeof record.resource !== "string" || record.resource !== canonicalizeResourceIndicator(record.resource) ||
|
|
25
|
+
!Number.isSafeInteger(record.generation) || record.generation < 0 ||
|
|
26
|
+
(record.session !== null && (!isStoredOAuthSession(record.session) || record.session.resource !== record.resource)) ||
|
|
27
|
+
typeof record.clients !== "object" || record.clients === null || Array.isArray(record.clients))
|
|
28
|
+
throw new Error("Invalid stored OAuth resource identity; reset explicitly to recover");
|
|
29
|
+
let resourceUrl;
|
|
30
|
+
try {
|
|
31
|
+
resourceUrl = new URL(record.resource);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
throw new Error("Invalid stored OAuth resource identity URL");
|
|
35
|
+
}
|
|
36
|
+
if (!["http:", "https:"].includes(resourceUrl.protocol) || resourceUrl.username || resourceUrl.password || resourceUrl.hash)
|
|
37
|
+
throw new Error("Invalid stored OAuth resource identity URL");
|
|
38
|
+
for (const [issuer, client] of Object.entries(record.clients)) {
|
|
39
|
+
const normalized = normalizeStoredOAuthClient(client);
|
|
40
|
+
let url;
|
|
41
|
+
try {
|
|
42
|
+
url = new URL(issuer);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
throw new Error("Invalid stored OAuth resource client issuer");
|
|
46
|
+
}
|
|
47
|
+
if (normalized === null || !["http:", "https:"].includes(url.protocol) || url.username || url.password || url.hash)
|
|
48
|
+
throw new Error("Invalid stored OAuth resource client");
|
|
49
|
+
Object.defineProperty(record.clients, issuer, { value: normalized, enumerable: true, configurable: true, writable: true });
|
|
50
|
+
}
|
|
51
|
+
return record;
|
|
52
|
+
}
|
|
53
|
+
async function reconcile(resource) {
|
|
54
|
+
resource = canonicalizeResourceIndicator(resource);
|
|
55
|
+
const existing = await read();
|
|
56
|
+
if (existing?.resource === resource) {
|
|
57
|
+
result.initialGrantAllowed = existing.generation === 0;
|
|
58
|
+
return existing;
|
|
59
|
+
}
|
|
60
|
+
const record = { version: 1, resource, generation: existing === null ? 0 : existing.generation + 1, session: null, clients: {} };
|
|
61
|
+
if (!Number.isSafeInteger(record.generation))
|
|
62
|
+
throw new Error("OAuth resource identity generation limit exceeded");
|
|
63
|
+
await store.set(JSON.stringify(record));
|
|
64
|
+
result.initialGrantAllowed = record.generation === 0;
|
|
65
|
+
return record;
|
|
66
|
+
}
|
|
67
|
+
result.sessionStore = {
|
|
68
|
+
async withLock(resource, operation, options) {
|
|
69
|
+
if (store.withLock === undefined)
|
|
70
|
+
throw new Error("OAuth resource identity backend must support transaction locks");
|
|
71
|
+
return store.withLock(async () => {
|
|
72
|
+
options.signal?.throwIfAborted();
|
|
73
|
+
await reconcile(resource);
|
|
74
|
+
options.signal?.throwIfAborted();
|
|
75
|
+
return operation();
|
|
76
|
+
}, options);
|
|
77
|
+
},
|
|
78
|
+
async load(resource) {
|
|
79
|
+
// Unauthorized provenance may peek before acquiring the transaction lock.
|
|
80
|
+
// Only the lock owner may adopt a URL or retire the previous credentials.
|
|
81
|
+
const record = await read();
|
|
82
|
+
return record?.resource === canonicalizeResourceIndicator(resource) ? record.session : null;
|
|
83
|
+
},
|
|
84
|
+
async save(resource, session) {
|
|
85
|
+
const record = await reconcile(resource);
|
|
86
|
+
if (canonicalizeResourceIndicator(session.resource) !== record.resource)
|
|
87
|
+
throw new Error("OAuth session does not match its resource identity");
|
|
88
|
+
record.session = session;
|
|
89
|
+
await store.set(JSON.stringify(record));
|
|
90
|
+
},
|
|
91
|
+
async clear(resource) {
|
|
92
|
+
const record = await reconcile(resource);
|
|
93
|
+
record.session = null;
|
|
94
|
+
// Preserve a tombstone so environment grants cannot revive a cleared family.
|
|
95
|
+
record.generation = Math.max(1, record.generation);
|
|
96
|
+
result.initialGrantAllowed = false;
|
|
97
|
+
await store.set(JSON.stringify(record));
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
result.clientStore = {
|
|
101
|
+
async load(issuer) { const record = await read(); return record !== null && Object.hasOwn(record.clients, issuer) ? record.clients[issuer] : null; },
|
|
102
|
+
async save(issuer, client) {
|
|
103
|
+
const record = await read();
|
|
104
|
+
if (record === null)
|
|
105
|
+
throw new Error("OAuth resource identity must be bound before registering a client");
|
|
106
|
+
Object.defineProperty(record.clients, issuer, { value: client, enumerable: true, configurable: true, writable: true });
|
|
107
|
+
await store.set(JSON.stringify(record));
|
|
108
|
+
},
|
|
109
|
+
async clear(issuer) {
|
|
110
|
+
const record = await read();
|
|
111
|
+
if (record === null || !Object.hasOwn(record.clients, issuer))
|
|
112
|
+
return;
|
|
113
|
+
delete record.clients[issuer];
|
|
114
|
+
await store.set(JSON.stringify(record));
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
@@ -147,6 +147,8 @@ export interface DefaultOAuthClientProviderOptions {
|
|
|
147
147
|
sessionLockTimeoutMs?: number;
|
|
148
148
|
/** Isolate native persisted sessions and registrations for a named profile. */
|
|
149
149
|
persistenceNamespace?: string;
|
|
150
|
+
/** Native-owned durable logical server identity; changing URL retires its credentials. */
|
|
151
|
+
resourceIdentity?: string;
|
|
150
152
|
/** Import an existing grant for one resource. Persisted sessions take precedence. */
|
|
151
153
|
initialGrant?: {
|
|
152
154
|
resource: string;
|
|
@@ -250,6 +250,8 @@ interface DefaultOAuthClientProviderOptions {
|
|
|
250
250
|
sessionLockTimeoutMs?: number;
|
|
251
251
|
/** Isolate native persisted sessions and registrations for a named profile. */
|
|
252
252
|
persistenceNamespace?: string;
|
|
253
|
+
/** Native-owned durable logical server identity; changing URL retires its credentials. */
|
|
254
|
+
resourceIdentity?: string;
|
|
253
255
|
/** Import an existing grant for one resource. Persisted sessions take precedence. */
|
|
254
256
|
initialGrant?: {
|
|
255
257
|
resource: string;
|
|
@@ -4709,6 +4709,120 @@ function isNonBlankOwnString(record2, key2) {
|
|
|
4709
4709
|
return value !== void 0 && value.trim().length > 0;
|
|
4710
4710
|
}
|
|
4711
4711
|
|
|
4712
|
+
// ../mcp-oauth/dist/client/resource-bound-store.js
|
|
4713
|
+
function createResourceBoundOAuthStores(options, namespace, identity) {
|
|
4714
|
+
assertPersistenceNamespace(identity);
|
|
4715
|
+
const store = createNamedSecretStore(identity, options, {
|
|
4716
|
+
salt: "poe-code:mcp-oauth:resources:v1",
|
|
4717
|
+
directory: ".poe-code/mcp-oauth/resources",
|
|
4718
|
+
service: "poe-code-mcp-oauth-resources",
|
|
4719
|
+
accountPrefix: "resource"
|
|
4720
|
+
}, namespace);
|
|
4721
|
+
const result = { initialGrantAllowed: true, sessionStore: {}, clientStore: {} };
|
|
4722
|
+
async function read() {
|
|
4723
|
+
const raw = await store.get();
|
|
4724
|
+
if (raw === null)
|
|
4725
|
+
return null;
|
|
4726
|
+
let value;
|
|
4727
|
+
try {
|
|
4728
|
+
value = JSON.parse(raw);
|
|
4729
|
+
} catch {
|
|
4730
|
+
throw new Error("Stored OAuth resource identity must be valid JSON; reset explicitly to recover");
|
|
4731
|
+
}
|
|
4732
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
4733
|
+
throw new Error("Invalid stored OAuth resource identity");
|
|
4734
|
+
const record2 = value;
|
|
4735
|
+
if (!["version", "resource", "generation", "session", "clients"].every((key2) => Object.hasOwn(record2, key2)) || record2.version !== 1 || typeof record2.resource !== "string" || record2.resource !== canonicalizeResourceIndicator(record2.resource) || !Number.isSafeInteger(record2.generation) || record2.generation < 0 || record2.session !== null && (!isStoredOAuthSession(record2.session) || record2.session.resource !== record2.resource) || typeof record2.clients !== "object" || record2.clients === null || Array.isArray(record2.clients))
|
|
4736
|
+
throw new Error("Invalid stored OAuth resource identity; reset explicitly to recover");
|
|
4737
|
+
let resourceUrl;
|
|
4738
|
+
try {
|
|
4739
|
+
resourceUrl = new URL(record2.resource);
|
|
4740
|
+
} catch {
|
|
4741
|
+
throw new Error("Invalid stored OAuth resource identity URL");
|
|
4742
|
+
}
|
|
4743
|
+
if (!["http:", "https:"].includes(resourceUrl.protocol) || resourceUrl.username || resourceUrl.password || resourceUrl.hash)
|
|
4744
|
+
throw new Error("Invalid stored OAuth resource identity URL");
|
|
4745
|
+
for (const [issuer, client] of Object.entries(record2.clients)) {
|
|
4746
|
+
const normalized = normalizeStoredOAuthClient(client);
|
|
4747
|
+
let url;
|
|
4748
|
+
try {
|
|
4749
|
+
url = new URL(issuer);
|
|
4750
|
+
} catch {
|
|
4751
|
+
throw new Error("Invalid stored OAuth resource client issuer");
|
|
4752
|
+
}
|
|
4753
|
+
if (normalized === null || !["http:", "https:"].includes(url.protocol) || url.username || url.password || url.hash)
|
|
4754
|
+
throw new Error("Invalid stored OAuth resource client");
|
|
4755
|
+
Object.defineProperty(record2.clients, issuer, { value: normalized, enumerable: true, configurable: true, writable: true });
|
|
4756
|
+
}
|
|
4757
|
+
return record2;
|
|
4758
|
+
}
|
|
4759
|
+
async function reconcile(resource) {
|
|
4760
|
+
resource = canonicalizeResourceIndicator(resource);
|
|
4761
|
+
const existing = await read();
|
|
4762
|
+
if (existing?.resource === resource) {
|
|
4763
|
+
result.initialGrantAllowed = existing.generation === 0;
|
|
4764
|
+
return existing;
|
|
4765
|
+
}
|
|
4766
|
+
const record2 = { version: 1, resource, generation: existing === null ? 0 : existing.generation + 1, session: null, clients: {} };
|
|
4767
|
+
if (!Number.isSafeInteger(record2.generation))
|
|
4768
|
+
throw new Error("OAuth resource identity generation limit exceeded");
|
|
4769
|
+
await store.set(JSON.stringify(record2));
|
|
4770
|
+
result.initialGrantAllowed = record2.generation === 0;
|
|
4771
|
+
return record2;
|
|
4772
|
+
}
|
|
4773
|
+
result.sessionStore = {
|
|
4774
|
+
async withLock(resource, operation, options2) {
|
|
4775
|
+
if (store.withLock === void 0)
|
|
4776
|
+
throw new Error("OAuth resource identity backend must support transaction locks");
|
|
4777
|
+
return store.withLock(async () => {
|
|
4778
|
+
options2.signal?.throwIfAborted();
|
|
4779
|
+
await reconcile(resource);
|
|
4780
|
+
options2.signal?.throwIfAborted();
|
|
4781
|
+
return operation();
|
|
4782
|
+
}, options2);
|
|
4783
|
+
},
|
|
4784
|
+
async load(resource) {
|
|
4785
|
+
const record2 = await read();
|
|
4786
|
+
return record2?.resource === canonicalizeResourceIndicator(resource) ? record2.session : null;
|
|
4787
|
+
},
|
|
4788
|
+
async save(resource, session) {
|
|
4789
|
+
const record2 = await reconcile(resource);
|
|
4790
|
+
if (canonicalizeResourceIndicator(session.resource) !== record2.resource)
|
|
4791
|
+
throw new Error("OAuth session does not match its resource identity");
|
|
4792
|
+
record2.session = session;
|
|
4793
|
+
await store.set(JSON.stringify(record2));
|
|
4794
|
+
},
|
|
4795
|
+
async clear(resource) {
|
|
4796
|
+
const record2 = await reconcile(resource);
|
|
4797
|
+
record2.session = null;
|
|
4798
|
+
record2.generation = Math.max(1, record2.generation);
|
|
4799
|
+
result.initialGrantAllowed = false;
|
|
4800
|
+
await store.set(JSON.stringify(record2));
|
|
4801
|
+
}
|
|
4802
|
+
};
|
|
4803
|
+
result.clientStore = {
|
|
4804
|
+
async load(issuer) {
|
|
4805
|
+
const record2 = await read();
|
|
4806
|
+
return record2 !== null && Object.hasOwn(record2.clients, issuer) ? record2.clients[issuer] : null;
|
|
4807
|
+
},
|
|
4808
|
+
async save(issuer, client) {
|
|
4809
|
+
const record2 = await read();
|
|
4810
|
+
if (record2 === null)
|
|
4811
|
+
throw new Error("OAuth resource identity must be bound before registering a client");
|
|
4812
|
+
Object.defineProperty(record2.clients, issuer, { value: client, enumerable: true, configurable: true, writable: true });
|
|
4813
|
+
await store.set(JSON.stringify(record2));
|
|
4814
|
+
},
|
|
4815
|
+
async clear(issuer) {
|
|
4816
|
+
const record2 = await read();
|
|
4817
|
+
if (record2 === null || !Object.hasOwn(record2.clients, issuer))
|
|
4818
|
+
return;
|
|
4819
|
+
delete record2.clients[issuer];
|
|
4820
|
+
await store.set(JSON.stringify(record2));
|
|
4821
|
+
}
|
|
4822
|
+
};
|
|
4823
|
+
return result;
|
|
4824
|
+
}
|
|
4825
|
+
|
|
4712
4826
|
// ../mcp-oauth/dist/client/default-oauth-client-provider.js
|
|
4713
4827
|
import { isIP } from "node:net";
|
|
4714
4828
|
|
|
@@ -5023,8 +5137,11 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5023
5137
|
const configuredClient = normalizeConfiguredClient(options.client);
|
|
5024
5138
|
const requestedTokenMethod = normalizeOAuthTokenEndpointAuthMethod(options.client.tokenEndpointAuthMethod);
|
|
5025
5139
|
const configuredTokenMethod = requestedTokenMethod ?? configuredClient?.tokenEndpointAuthMethod;
|
|
5026
|
-
|
|
5027
|
-
|
|
5140
|
+
if (options.resourceIdentity !== void 0 && options.sessionStore !== void 0)
|
|
5141
|
+
throw new Error("OAuth resourceIdentity requires native-owned persistence; custom stores own their resource trust policy");
|
|
5142
|
+
const resourceStores = options.resourceIdentity === void 0 ? void 0 : createResourceBoundOAuthStores(options.authStore ?? {}, options.persistenceNamespace, options.resourceIdentity);
|
|
5143
|
+
const sessionStore = resourceStores?.sessionStore ?? options.sessionStore ?? createAuthStoreSessionStore(options.authStore, options.persistenceNamespace);
|
|
5144
|
+
const clientStore = resourceStores?.clientStore ?? (options.authStore === void 0 ? null : createAuthStoreClientStore(options.authStore, options.persistenceNamespace));
|
|
5028
5145
|
const now = options.now ?? Date.now;
|
|
5029
5146
|
const registeredClients = /* @__PURE__ */ new Map();
|
|
5030
5147
|
if (options.initialGrant !== void 0) {
|
|
@@ -5117,6 +5234,11 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5117
5234
|
const canonicalResource = canonicalizeResourceIndicator(resource);
|
|
5118
5235
|
return withOAuthSessionTransaction(sessionStore, canonicalResource, async () => {
|
|
5119
5236
|
let session = await loadSession(canonicalResource);
|
|
5237
|
+
if (resourceStores !== void 0) {
|
|
5238
|
+
registeredClients.clear();
|
|
5239
|
+
if (!resourceStores.initialGrantAllowed)
|
|
5240
|
+
initialGrantConsumed = true;
|
|
5241
|
+
}
|
|
5120
5242
|
if (session !== null)
|
|
5121
5243
|
assertRegistrationIssuer(session.client, session.authorizationServer);
|
|
5122
5244
|
if (configuredClient !== null && discovery !== void 0)
|