tiny-http-mcp-server 0.1.32 → 0.1.33
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 +7 -0
- package/node_modules/mcp-oauth/dist/client/auth-store-session-store.d.ts +1 -6
- package/node_modules/mcp-oauth/dist/client/auth-store-session-store.js +6 -18
- package/node_modules/mcp-oauth/dist/client/client-registration.d.ts +4 -0
- package/node_modules/mcp-oauth/dist/client/client-registration.js +94 -0
- package/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +18 -40
- package/node_modules/mcp-oauth/dist/client/types.d.ts +21 -4
- package/node_modules/mcp-oauth/dist/index.d.ts +2 -1
- package/node_modules/mcp-oauth/dist/index.js +1 -0
- package/node_modules/tiny-mcp-client/dist/index.d.ts +21 -4
- package/node_modules/tiny-mcp-client/dist/index.js +138 -64
- package/package.json +1 -1
package/dist/composition.json
CHANGED
|
@@ -112,6 +112,13 @@ Discovery binds an expired or explicitly rejected grant before silent refresh,
|
|
|
112
112
|
using the original configured client. Persisted sessions take precedence,
|
|
113
113
|
including sessions whose tokens have been cleared; an import cannot revive them.
|
|
114
114
|
Input tokens are copied and invalid expiry values fail before authorization.
|
|
115
|
+
Pass a complete DCR response as `client.registration` (or validate untrusted JSON
|
|
116
|
+
with `parseOAuthClientRegistration`). Dynamic clients infer their original ID
|
|
117
|
+
and secret from that response and reuse it without registering another app.
|
|
118
|
+
Explicit ID/secret values must agree with the imported response. Sessions and
|
|
119
|
+
native registration stores retain arrays, issuance/expiry timestamps and JSON
|
|
120
|
+
provider metadata. Registration input is copied, bounded to 64 KiB and 64
|
|
121
|
+
levels, and rejects invalid standard field types and non-JSON extensions.
|
|
115
122
|
Static clients and dynamic initial-grant imports require cached grants to match
|
|
116
123
|
the original normalized client ID and secret. A different client configuration
|
|
117
124
|
fails before attaching or refreshing credentials and retains the stored record;
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { type CreateSecretStoreInput } from "auth-store";
|
|
2
|
-
import type { OAuthSessionStore } from "./types.js";
|
|
3
|
-
interface StoredOAuthClient {
|
|
4
|
-
clientId: string;
|
|
5
|
-
clientSecret?: string;
|
|
6
|
-
}
|
|
2
|
+
import type { OAuthSessionStore, StoredOAuthClient } from "./types.js";
|
|
7
3
|
export interface OAuthClientStore {
|
|
8
4
|
load(issuer: string): Promise<StoredOAuthClient | null>;
|
|
9
5
|
save(issuer: string, client: StoredOAuthClient): Promise<void>;
|
|
@@ -12,4 +8,3 @@ export interface OAuthClientStore {
|
|
|
12
8
|
export declare function createAuthStoreSessionStore(options?: CreateSecretStoreInput, namespace?: string): OAuthSessionStore;
|
|
13
9
|
export declare function createAuthStoreClientStore(options: CreateSecretStoreInput, namespace?: string): OAuthClientStore;
|
|
14
10
|
export declare function assertPersistenceNamespace(namespace: string | undefined): void;
|
|
15
|
-
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeStoredOAuthClient } from "./client-registration.js";
|
|
1
2
|
import crypto from "node:crypto";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { createSecretStore } from "auth-store";
|
|
@@ -62,15 +63,10 @@ export function createAuthStoreClientStore(options, namespace) {
|
|
|
62
63
|
catch {
|
|
63
64
|
throw new Error("Stored OAuth client must be valid JSON; reset the store explicitly to recover");
|
|
64
65
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
Object.prototype.hasOwnProperty.call(parsed, "clientSecret")) {
|
|
70
|
-
client.clientSecret = getOwnEntry(parsed, "clientSecret");
|
|
71
|
-
}
|
|
72
|
-
return client;
|
|
73
|
-
}
|
|
66
|
+
// Preserve all registration metadata; provider normalization validates its
|
|
67
|
+
// identity and schema before it can authorize a request.
|
|
68
|
+
if (isObjectRecord(parsed) && typeof getOwnEntry(parsed, "clientId") === "string")
|
|
69
|
+
return parsed;
|
|
74
70
|
throw new Error("Stored OAuth client must be a JSON object with clientId");
|
|
75
71
|
},
|
|
76
72
|
async save(issuer, client) {
|
|
@@ -142,21 +138,13 @@ function isStoredOAuthSession(value) {
|
|
|
142
138
|
}
|
|
143
139
|
return (isNonBlankOwnString(value, "resource") &&
|
|
144
140
|
isNonBlankOwnString(value, "authorizationServer") &&
|
|
145
|
-
|
|
141
|
+
normalizeStoredOAuthClient(getOwnEntry(value, "client")) !== null &&
|
|
146
142
|
isStoredOAuthDiscovery(getOwnEntry(value, "discovery")) &&
|
|
147
143
|
(getOwnEntry(value, "requestedScope") === undefined || isNonBlankOwnString(value, "requestedScope")) &&
|
|
148
144
|
(getOwnEntry(value, "refreshState") === undefined ||
|
|
149
145
|
(getOwnEntry(value, "refreshState") === "pending" && getOwnEntry(value, "tokens") === undefined)) &&
|
|
150
146
|
isStoredOAuthTokensOrMissing(getOwnEntry(value, "tokens")));
|
|
151
147
|
}
|
|
152
|
-
function isStoredOAuthClient(value) {
|
|
153
|
-
if (!isObjectRecord(value) || !isNonBlankOwnString(value, "clientId")) {
|
|
154
|
-
return false;
|
|
155
|
-
}
|
|
156
|
-
const clientSecret = getOwnEntry(value, "clientSecret");
|
|
157
|
-
return (clientSecret === undefined ||
|
|
158
|
-
(typeof clientSecret === "string" && clientSecret.trim().length > 0));
|
|
159
|
-
}
|
|
160
148
|
function isStoredOAuthDiscovery(value) {
|
|
161
149
|
if (!isObjectRecord(value)) {
|
|
162
150
|
return false;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { OAuthClientRegistration, StoredOAuthClient } from "./types.js";
|
|
2
|
+
/** Validate and copy a bounded JSON DCR response without quoting credential input. */
|
|
3
|
+
export declare function parseOAuthClientRegistration(value: unknown): OAuthClientRegistration;
|
|
4
|
+
export declare function normalizeStoredOAuthClient(value: unknown): StoredOAuthClient | null;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { normalizeOAuthScope } from "./scope.js";
|
|
2
|
+
/** Validate and copy a bounded JSON DCR response without quoting credential input. */
|
|
3
|
+
export function parseOAuthClientRegistration(value) {
|
|
4
|
+
const invalid = () => new Error("Invalid OAuth client registration metadata");
|
|
5
|
+
let nodes = 0;
|
|
6
|
+
function copy(input, depth) {
|
|
7
|
+
if (++nodes > 20_000 || depth > 64)
|
|
8
|
+
throw invalid();
|
|
9
|
+
if (input === null || typeof input === "boolean" || typeof input === "string")
|
|
10
|
+
return input;
|
|
11
|
+
if (typeof input === "number" && Number.isFinite(input))
|
|
12
|
+
return input;
|
|
13
|
+
if (typeof input !== "object" || input === null)
|
|
14
|
+
throw invalid();
|
|
15
|
+
const descriptors = Object.getOwnPropertyDescriptors(input);
|
|
16
|
+
if (Array.isArray(input)) {
|
|
17
|
+
const length = descriptors.length?.value;
|
|
18
|
+
if (length > 20_000)
|
|
19
|
+
throw invalid();
|
|
20
|
+
const result = [];
|
|
21
|
+
for (let index = 0; index < length; index++) {
|
|
22
|
+
const descriptor = descriptors[String(index)];
|
|
23
|
+
if (descriptor === undefined || !Object.hasOwn(descriptor, "value"))
|
|
24
|
+
throw invalid();
|
|
25
|
+
result.push(copy(descriptor.value, depth + 1));
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
if (Object.getPrototypeOf(input) !== Object.prototype && Object.getPrototypeOf(input) !== null)
|
|
30
|
+
throw invalid();
|
|
31
|
+
return Object.fromEntries(Object.entries(descriptors).filter(([, descriptor]) => descriptor.enumerable).map(([key, descriptor]) => {
|
|
32
|
+
if (!Object.hasOwn(descriptor, "value"))
|
|
33
|
+
throw invalid();
|
|
34
|
+
return [key, copy(descriptor.value, depth + 1)];
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
let result;
|
|
38
|
+
try {
|
|
39
|
+
result = copy(value, 0);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
throw invalid();
|
|
43
|
+
}
|
|
44
|
+
if (typeof result !== "object" || result === null || Array.isArray(result))
|
|
45
|
+
throw invalid();
|
|
46
|
+
const record = result;
|
|
47
|
+
if (!Object.hasOwn(record, "client_id") || typeof record.client_id !== "string" || record.client_id.trim() === "")
|
|
48
|
+
throw new Error("OAuth client registration response missing client_id");
|
|
49
|
+
for (const key of ["client_id", "client_secret", "token_endpoint_auth_method", "application_type", "client_name", "client_uri", "logo_uri", "scope",
|
|
50
|
+
"tos_uri", "policy_uri", "jwks_uri", "software_id", "software_version", "software_statement", "registration_access_token", "registration_client_uri", "issuer"]) {
|
|
51
|
+
if (Object.hasOwn(record, key) && record[key] !== null && typeof record[key] !== "string")
|
|
52
|
+
throw invalid();
|
|
53
|
+
}
|
|
54
|
+
if (typeof record.client_secret === "string" && record.client_secret.trim() === "")
|
|
55
|
+
throw invalid();
|
|
56
|
+
for (const key of ["redirect_uris", "grant_types", "response_types", "contacts"]) {
|
|
57
|
+
const entry = record[key];
|
|
58
|
+
if (Object.hasOwn(record, key) && entry !== null && (!Array.isArray(entry) || entry.some(item => typeof item !== "string")))
|
|
59
|
+
throw invalid();
|
|
60
|
+
}
|
|
61
|
+
for (const key of ["client_id_issued_at", "client_secret_expires_at"]) {
|
|
62
|
+
const entry = record[key];
|
|
63
|
+
if (Object.hasOwn(record, key) && entry !== null && (typeof entry !== "number" || !Number.isSafeInteger(entry) || entry < 0))
|
|
64
|
+
throw invalid();
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
normalizeOAuthScope(Object.hasOwn(record, "scope") && record.scope !== null ? record.scope : undefined);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
throw invalid();
|
|
71
|
+
}
|
|
72
|
+
if (Buffer.byteLength(JSON.stringify(record), "utf8") > 64 * 1024)
|
|
73
|
+
throw invalid();
|
|
74
|
+
return record;
|
|
75
|
+
}
|
|
76
|
+
export function normalizeStoredOAuthClient(value) {
|
|
77
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
78
|
+
return null;
|
|
79
|
+
const record = value;
|
|
80
|
+
const clientId = Object.hasOwn(record, "clientId") ? record.clientId : undefined;
|
|
81
|
+
const clientSecret = Object.hasOwn(record, "clientSecret") ? record.clientSecret : undefined;
|
|
82
|
+
if (typeof clientId !== "string" || clientId.trim() === "" ||
|
|
83
|
+
(clientSecret !== undefined && (typeof clientSecret !== "string" || clientSecret.trim() === "")))
|
|
84
|
+
return null;
|
|
85
|
+
const client = { clientId: clientId.trim(), ...(clientSecret === undefined ? {} : { clientSecret: clientSecret.trim() }) };
|
|
86
|
+
if (Object.hasOwn(record, "registration") && record.registration !== undefined) {
|
|
87
|
+
const registration = parseOAuthClientRegistration(record.registration);
|
|
88
|
+
const registeredSecret = Object.hasOwn(registration, "client_secret") ? registration.client_secret?.trim() : undefined;
|
|
89
|
+
if (registration.client_id.trim() !== client.clientId || registeredSecret !== client.clientSecret)
|
|
90
|
+
throw new Error("OAuth client registration does not match the client identity");
|
|
91
|
+
client.registration = registration;
|
|
92
|
+
}
|
|
93
|
+
return client;
|
|
94
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeStoredOAuthClient, parseOAuthClientRegistration } from "./client-registration.js";
|
|
1
2
|
import { normalizeOAuthScope } from "./scope.js";
|
|
2
3
|
import { isIP } from "node:net";
|
|
3
4
|
import { fetchMcpResponse } from "../http-fetch.js";
|
|
@@ -21,6 +22,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
21
22
|
assertPersistenceNamespace(options.persistenceNamespace);
|
|
22
23
|
const clientMetadata = getClientMetadata(options.client);
|
|
23
24
|
const requestedScope = clientMetadata?.scope;
|
|
25
|
+
const configuredClient = normalizeConfiguredClient(options.client);
|
|
24
26
|
const sessionStore = options.sessionStore ?? createAuthStoreSessionStore(options.authStore, options.persistenceNamespace);
|
|
25
27
|
const clientStore = options.authStore === undefined ? null : createAuthStoreClientStore(options.authStore, options.persistenceNamespace);
|
|
26
28
|
const now = options.now ?? Date.now;
|
|
@@ -39,7 +41,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
39
41
|
const initialGrant = options.initialGrant === undefined ? undefined : {
|
|
40
42
|
resource: canonicalizeResourceIndicator(options.initialGrant.resource),
|
|
41
43
|
tokens: normalizeStoredTokens(options.initialGrant.tokens),
|
|
42
|
-
client:
|
|
44
|
+
client: configuredClient
|
|
43
45
|
};
|
|
44
46
|
if (initialGrant !== undefined && (initialGrant.tokens === undefined || initialGrant.client === null))
|
|
45
47
|
throw new Error("OAuth initial grant requires valid tokens and the original client ID");
|
|
@@ -147,8 +149,8 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
147
149
|
if (forceRefresh && rejectedTokens !== undefined && (rejectedTokens === null || session?.tokens === undefined || !sameTokenGrant(session.tokens, rejectedTokens)))
|
|
148
150
|
forceRefresh = false;
|
|
149
151
|
const sessionDiscovery = resolveDiscovery(discovery, session);
|
|
150
|
-
if ((options.client.mode === "static" || initialGrant !== undefined) && session !== null && (session.tokens !== undefined || session.refreshState === "pending")) {
|
|
151
|
-
const configured =
|
|
152
|
+
if ((options.client.mode === "static" || configuredClient?.registration !== undefined || initialGrant !== undefined) && session !== null && (session.tokens !== undefined || session.refreshState === "pending")) {
|
|
153
|
+
const configured = configuredClient;
|
|
152
154
|
if (configured === null || configured.clientId !== session.client.clientId || configured.clientSecret !== session.client.clientSecret)
|
|
153
155
|
throw new Error("Stored session belongs to a different OAuth client; use separate persistence or explicitly reset it");
|
|
154
156
|
}
|
|
@@ -327,8 +329,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
327
329
|
}
|
|
328
330
|
async function resolveClient(existingSession, discovery, redirectUri, fetch, parentSignal) {
|
|
329
331
|
parentSignal?.throwIfAborted();
|
|
330
|
-
|
|
331
|
-
if (options.client.mode === "static") {
|
|
332
|
+
if (options.client.mode === "static" || configuredClient?.registration !== undefined) {
|
|
332
333
|
if (configuredClient === null) {
|
|
333
334
|
throw new Error("OAuth client_id must not be blank");
|
|
334
335
|
}
|
|
@@ -389,16 +390,12 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
389
390
|
signal
|
|
390
391
|
});
|
|
391
392
|
const payload = await readOAuthJsonObjectResponse(response, signal);
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
throw new Error("OAuth client registration response missing client_id");
|
|
395
|
-
}
|
|
396
|
-
const clientSecret = getOwnString(payload, "client_secret");
|
|
393
|
+
const registration = parseOAuthClientRegistration(payload);
|
|
394
|
+
const registeredSecret = getOwnString(registration, "client_secret");
|
|
397
395
|
const registeredClient = {
|
|
398
|
-
clientId:
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
: undefined
|
|
396
|
+
clientId: registration.client_id.trim(),
|
|
397
|
+
...(registeredSecret === undefined ? {} : { clientSecret: registeredSecret.trim() }),
|
|
398
|
+
registration
|
|
402
399
|
};
|
|
403
400
|
await saveRegisteredClient(discovery.authorizationServer, registeredClient);
|
|
404
401
|
return {
|
|
@@ -424,7 +421,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
424
421
|
return null;
|
|
425
422
|
}
|
|
426
423
|
const client = await clientStore.load(issuer);
|
|
427
|
-
const normalizedClient = client === null ? null :
|
|
424
|
+
const normalizedClient = client === null ? null : normalizeStoredOAuthClient(client);
|
|
428
425
|
if (client !== null && normalizedClient === null) {
|
|
429
426
|
await clientStore.clear(issuer);
|
|
430
427
|
return null;
|
|
@@ -503,7 +500,7 @@ function normalizeLoadedSession(session) {
|
|
|
503
500
|
const refreshState = getOwnEntry(session, "refreshState");
|
|
504
501
|
if (refreshState !== undefined && (refreshState !== "pending" || getOwnEntry(session, "tokens") !== undefined))
|
|
505
502
|
throw new Error("Stored OAuth refresh state is invalid");
|
|
506
|
-
const client =
|
|
503
|
+
const client = normalizeStoredOAuthClient(getOwnEntry(session, "client"));
|
|
507
504
|
if (client === null) {
|
|
508
505
|
return { ...session, client: { clientId: "" }, tokens: undefined };
|
|
509
506
|
}
|
|
@@ -513,25 +510,6 @@ function normalizeLoadedSession(session) {
|
|
|
513
510
|
tokens: normalizeStoredTokens(getOwnEntry(session, "tokens"))
|
|
514
511
|
};
|
|
515
512
|
}
|
|
516
|
-
function normalizeStoredClient(value) {
|
|
517
|
-
if (!isObjectRecord(value)) {
|
|
518
|
-
return null;
|
|
519
|
-
}
|
|
520
|
-
const clientId = getOwnString(value, "clientId");
|
|
521
|
-
if (clientId === undefined || clientId.trim().length === 0) {
|
|
522
|
-
return null;
|
|
523
|
-
}
|
|
524
|
-
const normalizedClientId = clientId.trim();
|
|
525
|
-
const clientSecret = getOwnEntry(value, "clientSecret");
|
|
526
|
-
if (clientSecret === undefined) {
|
|
527
|
-
return { clientId: normalizedClientId };
|
|
528
|
-
}
|
|
529
|
-
if (typeof clientSecret !== "string" || clientSecret.trim().length === 0) {
|
|
530
|
-
return null;
|
|
531
|
-
}
|
|
532
|
-
const normalizedClientSecret = clientSecret.trim();
|
|
533
|
-
return { clientId: normalizedClientId, clientSecret: normalizedClientSecret };
|
|
534
|
-
}
|
|
535
513
|
function normalizeStoredTokens(value) {
|
|
536
514
|
if (value === undefined || !isObjectRecord(value)) {
|
|
537
515
|
return undefined;
|
|
@@ -581,12 +559,12 @@ function getClientMetadata(client) {
|
|
|
581
559
|
};
|
|
582
560
|
}
|
|
583
561
|
function normalizeConfiguredClient(client) {
|
|
584
|
-
const
|
|
585
|
-
|
|
562
|
+
const registration = client.registration === undefined ? undefined : parseOAuthClientRegistration(client.registration);
|
|
563
|
+
const clientId = normalizeOptionalOAuthString(client.clientId) ?? registration?.client_id.trim();
|
|
564
|
+
if (clientId === undefined)
|
|
586
565
|
return null;
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
return clientSecret === undefined ? { clientId } : { clientId, clientSecret };
|
|
566
|
+
const clientSecret = normalizeOptionalOAuthString(client.clientSecret) ?? (registration === undefined ? undefined : getOwnString(registration, "client_secret")?.trim());
|
|
567
|
+
return normalizeStoredOAuthClient({ clientId, clientSecret, registration });
|
|
590
568
|
}
|
|
591
569
|
function normalizeOptionalOAuthString(value) {
|
|
592
570
|
if (value === undefined) {
|
|
@@ -70,13 +70,27 @@ export interface StoredOAuthTokens {
|
|
|
70
70
|
expiresAt: number | null;
|
|
71
71
|
scope?: string;
|
|
72
72
|
}
|
|
73
|
+
/** Full RFC 7591 response, including JSON provider extensions. */
|
|
74
|
+
export interface OAuthClientRegistration extends Record<string, unknown> {
|
|
75
|
+
client_id: string;
|
|
76
|
+
client_secret?: string | null;
|
|
77
|
+
redirect_uris?: string[] | null;
|
|
78
|
+
grant_types?: string[] | null;
|
|
79
|
+
response_types?: string[] | null;
|
|
80
|
+
contacts?: string[] | null;
|
|
81
|
+
client_id_issued_at?: number | null;
|
|
82
|
+
client_secret_expires_at?: number | null;
|
|
83
|
+
token_endpoint_auth_method?: string | null;
|
|
84
|
+
}
|
|
85
|
+
export interface StoredOAuthClient {
|
|
86
|
+
clientId: string;
|
|
87
|
+
clientSecret?: string;
|
|
88
|
+
registration?: OAuthClientRegistration;
|
|
89
|
+
}
|
|
73
90
|
export interface StoredOAuthSession {
|
|
74
91
|
resource: string;
|
|
75
92
|
authorizationServer: string;
|
|
76
|
-
client:
|
|
77
|
-
clientId: string;
|
|
78
|
-
clientSecret?: string;
|
|
79
|
-
};
|
|
93
|
+
client: StoredOAuthClient;
|
|
80
94
|
tokens?: StoredOAuthTokens;
|
|
81
95
|
/** A refresh was begun; its winning response may not have been persisted. */
|
|
82
96
|
refreshState?: "pending";
|
|
@@ -104,11 +118,14 @@ export interface DefaultOAuthClientProviderOptions {
|
|
|
104
118
|
clientId?: string;
|
|
105
119
|
clientSecret?: string;
|
|
106
120
|
metadata?: OAuthClientMetadata;
|
|
121
|
+
/** Import a complete registration owned by the caller. */
|
|
122
|
+
registration?: OAuthClientRegistration;
|
|
107
123
|
} | {
|
|
108
124
|
mode: "static";
|
|
109
125
|
clientId: string;
|
|
110
126
|
clientSecret?: string;
|
|
111
127
|
metadata?: OAuthClientMetadata;
|
|
128
|
+
registration?: OAuthClientRegistration;
|
|
112
129
|
};
|
|
113
130
|
/** Disable interactive authorization while allowing cached tokens and silent refresh. */
|
|
114
131
|
allowInteractive?: boolean;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export { createAuthStoreSessionStore, } from "./client/auth-store-session-store.js";
|
|
2
|
+
export { parseOAuthClientRegistration } from "./client/client-registration.js";
|
|
2
3
|
export { createDefaultOAuthClientProvider, createOAuthClientProvider, } from "./client/default-oauth-client-provider.js";
|
|
3
4
|
export { buildSuccessPage, createLoopbackAuthorizationSession, extractCodeFromInput, } from "./client/loopback-authorization.js";
|
|
4
5
|
export { generateCodeChallenge, generateCodeVerifier, } from "./client/pkce.js";
|
|
5
6
|
export { OAuthError, } from "./client/token-endpoint.js";
|
|
6
7
|
export { canonicalizeResourceIndicator, } from "./resource-indicator.js";
|
|
7
8
|
export { createJwksTokenVerifier, } from "./server/jwks-token-verifier.js";
|
|
8
|
-
export type { DefaultOAuthClientProviderOptions, OAuthAuthorizationServerMetadata, OAuthClientMetadata, OAuthClientProvider, OAuthClientProviderOptions, OAuthDiscoveryResult, OAuthMetadataFetch, OAuthProtectedResourceMetadata, OAuthSessionStore, OAuthUnauthorizedChallenge, StoredOAuthSession, StoredOAuthTokens, } from "./client/types.js";
|
|
9
|
+
export type { DefaultOAuthClientProviderOptions, OAuthAuthorizationServerMetadata, OAuthClientMetadata, OAuthClientRegistration, OAuthClientProvider, OAuthClientProviderOptions, OAuthDiscoveryResult, OAuthMetadataFetch, OAuthProtectedResourceMetadata, OAuthSessionStore, OAuthUnauthorizedChallenge, StoredOAuthSession, StoredOAuthClient, StoredOAuthTokens, } from "./client/types.js";
|
|
9
10
|
export type { JwksTokenVerifier, JwksTokenVerifierOptions, JwksVerifiedAccessToken, } from "./server/jwks-token-verifier.js";
|
|
10
11
|
export type { LoopbackAuthorizationOptions, LoopbackAuthorizationSession, OAuthLandingPage, } from "./client/loopback-authorization.js";
|
|
11
12
|
export { readBoundedResponseText } from "./http-response.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { createAuthStoreSessionStore, } from "./client/auth-store-session-store.js";
|
|
2
|
+
export { parseOAuthClientRegistration } from "./client/client-registration.js";
|
|
2
3
|
export { createDefaultOAuthClientProvider, createOAuthClientProvider, } from "./client/default-oauth-client-provider.js";
|
|
3
4
|
export { buildSuccessPage, createLoopbackAuthorizationSession, extractCodeFromInput, } from "./client/loopback-authorization.js";
|
|
4
5
|
export { generateCodeChallenge, generateCodeVerifier, } from "./client/pkce.js";
|
|
@@ -173,13 +173,27 @@ interface StoredOAuthTokens {
|
|
|
173
173
|
expiresAt: number | null;
|
|
174
174
|
scope?: string;
|
|
175
175
|
}
|
|
176
|
+
/** Full RFC 7591 response, including JSON provider extensions. */
|
|
177
|
+
interface OAuthClientRegistration extends Record<string, unknown> {
|
|
178
|
+
client_id: string;
|
|
179
|
+
client_secret?: string | null;
|
|
180
|
+
redirect_uris?: string[] | null;
|
|
181
|
+
grant_types?: string[] | null;
|
|
182
|
+
response_types?: string[] | null;
|
|
183
|
+
contacts?: string[] | null;
|
|
184
|
+
client_id_issued_at?: number | null;
|
|
185
|
+
client_secret_expires_at?: number | null;
|
|
186
|
+
token_endpoint_auth_method?: string | null;
|
|
187
|
+
}
|
|
188
|
+
interface StoredOAuthClient {
|
|
189
|
+
clientId: string;
|
|
190
|
+
clientSecret?: string;
|
|
191
|
+
registration?: OAuthClientRegistration;
|
|
192
|
+
}
|
|
176
193
|
interface StoredOAuthSession {
|
|
177
194
|
resource: string;
|
|
178
195
|
authorizationServer: string;
|
|
179
|
-
client:
|
|
180
|
-
clientId: string;
|
|
181
|
-
clientSecret?: string;
|
|
182
|
-
};
|
|
196
|
+
client: StoredOAuthClient;
|
|
183
197
|
tokens?: StoredOAuthTokens;
|
|
184
198
|
/** A refresh was begun; its winning response may not have been persisted. */
|
|
185
199
|
refreshState?: "pending";
|
|
@@ -207,11 +221,14 @@ interface DefaultOAuthClientProviderOptions {
|
|
|
207
221
|
clientId?: string;
|
|
208
222
|
clientSecret?: string;
|
|
209
223
|
metadata?: OAuthClientMetadata;
|
|
224
|
+
/** Import a complete registration owned by the caller. */
|
|
225
|
+
registration?: OAuthClientRegistration;
|
|
210
226
|
} | {
|
|
211
227
|
mode: "static";
|
|
212
228
|
clientId: string;
|
|
213
229
|
clientSecret?: string;
|
|
214
230
|
metadata?: OAuthClientMetadata;
|
|
231
|
+
registration?: OAuthClientRegistration;
|
|
215
232
|
};
|
|
216
233
|
/** Disable interactive authorization while allowing cached tokens and silent refresh. */
|
|
217
234
|
allowInteractive?: boolean;
|
|
@@ -3395,6 +3395,124 @@ 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/client-registration.js
|
|
3409
|
+
function parseOAuthClientRegistration(value) {
|
|
3410
|
+
const invalid = () => new Error("Invalid OAuth client registration metadata");
|
|
3411
|
+
let nodes = 0;
|
|
3412
|
+
function copy(input, depth) {
|
|
3413
|
+
if (++nodes > 2e4 || depth > 64)
|
|
3414
|
+
throw invalid();
|
|
3415
|
+
if (input === null || typeof input === "boolean" || typeof input === "string")
|
|
3416
|
+
return input;
|
|
3417
|
+
if (typeof input === "number" && Number.isFinite(input))
|
|
3418
|
+
return input;
|
|
3419
|
+
if (typeof input !== "object" || input === null)
|
|
3420
|
+
throw invalid();
|
|
3421
|
+
const descriptors = Object.getOwnPropertyDescriptors(input);
|
|
3422
|
+
if (Array.isArray(input)) {
|
|
3423
|
+
const length = descriptors.length?.value;
|
|
3424
|
+
if (length > 2e4)
|
|
3425
|
+
throw invalid();
|
|
3426
|
+
const result2 = [];
|
|
3427
|
+
for (let index = 0; index < length; index++) {
|
|
3428
|
+
const descriptor = descriptors[String(index)];
|
|
3429
|
+
if (descriptor === void 0 || !Object.hasOwn(descriptor, "value"))
|
|
3430
|
+
throw invalid();
|
|
3431
|
+
result2.push(copy(descriptor.value, depth + 1));
|
|
3432
|
+
}
|
|
3433
|
+
return result2;
|
|
3434
|
+
}
|
|
3435
|
+
if (Object.getPrototypeOf(input) !== Object.prototype && Object.getPrototypeOf(input) !== null)
|
|
3436
|
+
throw invalid();
|
|
3437
|
+
return Object.fromEntries(Object.entries(descriptors).filter(([, descriptor]) => descriptor.enumerable).map(([key2, descriptor]) => {
|
|
3438
|
+
if (!Object.hasOwn(descriptor, "value"))
|
|
3439
|
+
throw invalid();
|
|
3440
|
+
return [key2, copy(descriptor.value, depth + 1)];
|
|
3441
|
+
}));
|
|
3442
|
+
}
|
|
3443
|
+
let result;
|
|
3444
|
+
try {
|
|
3445
|
+
result = copy(value, 0);
|
|
3446
|
+
} catch {
|
|
3447
|
+
throw invalid();
|
|
3448
|
+
}
|
|
3449
|
+
if (typeof result !== "object" || result === null || Array.isArray(result))
|
|
3450
|
+
throw invalid();
|
|
3451
|
+
const record2 = result;
|
|
3452
|
+
if (!Object.hasOwn(record2, "client_id") || typeof record2.client_id !== "string" || record2.client_id.trim() === "")
|
|
3453
|
+
throw new Error("OAuth client registration response missing client_id");
|
|
3454
|
+
for (const key2 of [
|
|
3455
|
+
"client_id",
|
|
3456
|
+
"client_secret",
|
|
3457
|
+
"token_endpoint_auth_method",
|
|
3458
|
+
"application_type",
|
|
3459
|
+
"client_name",
|
|
3460
|
+
"client_uri",
|
|
3461
|
+
"logo_uri",
|
|
3462
|
+
"scope",
|
|
3463
|
+
"tos_uri",
|
|
3464
|
+
"policy_uri",
|
|
3465
|
+
"jwks_uri",
|
|
3466
|
+
"software_id",
|
|
3467
|
+
"software_version",
|
|
3468
|
+
"software_statement",
|
|
3469
|
+
"registration_access_token",
|
|
3470
|
+
"registration_client_uri",
|
|
3471
|
+
"issuer"
|
|
3472
|
+
]) {
|
|
3473
|
+
if (Object.hasOwn(record2, key2) && record2[key2] !== null && typeof record2[key2] !== "string")
|
|
3474
|
+
throw invalid();
|
|
3475
|
+
}
|
|
3476
|
+
if (typeof record2.client_secret === "string" && record2.client_secret.trim() === "")
|
|
3477
|
+
throw invalid();
|
|
3478
|
+
for (const key2 of ["redirect_uris", "grant_types", "response_types", "contacts"]) {
|
|
3479
|
+
const entry = record2[key2];
|
|
3480
|
+
if (Object.hasOwn(record2, key2) && entry !== null && (!Array.isArray(entry) || entry.some((item) => typeof item !== "string")))
|
|
3481
|
+
throw invalid();
|
|
3482
|
+
}
|
|
3483
|
+
for (const key2 of ["client_id_issued_at", "client_secret_expires_at"]) {
|
|
3484
|
+
const entry = record2[key2];
|
|
3485
|
+
if (Object.hasOwn(record2, key2) && entry !== null && (typeof entry !== "number" || !Number.isSafeInteger(entry) || entry < 0))
|
|
3486
|
+
throw invalid();
|
|
3487
|
+
}
|
|
3488
|
+
try {
|
|
3489
|
+
normalizeOAuthScope(Object.hasOwn(record2, "scope") && record2.scope !== null ? record2.scope : void 0);
|
|
3490
|
+
} catch {
|
|
3491
|
+
throw invalid();
|
|
3492
|
+
}
|
|
3493
|
+
if (Buffer.byteLength(JSON.stringify(record2), "utf8") > 64 * 1024)
|
|
3494
|
+
throw invalid();
|
|
3495
|
+
return record2;
|
|
3496
|
+
}
|
|
3497
|
+
function normalizeStoredOAuthClient(value) {
|
|
3498
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
3499
|
+
return null;
|
|
3500
|
+
const record2 = value;
|
|
3501
|
+
const clientId = Object.hasOwn(record2, "clientId") ? record2.clientId : void 0;
|
|
3502
|
+
const clientSecret = Object.hasOwn(record2, "clientSecret") ? record2.clientSecret : void 0;
|
|
3503
|
+
if (typeof clientId !== "string" || clientId.trim() === "" || clientSecret !== void 0 && (typeof clientSecret !== "string" || clientSecret.trim() === ""))
|
|
3504
|
+
return null;
|
|
3505
|
+
const client = { clientId: clientId.trim(), ...clientSecret === void 0 ? {} : { clientSecret: clientSecret.trim() } };
|
|
3506
|
+
if (Object.hasOwn(record2, "registration") && record2.registration !== void 0) {
|
|
3507
|
+
const registration = parseOAuthClientRegistration(record2.registration);
|
|
3508
|
+
const registeredSecret = Object.hasOwn(registration, "client_secret") ? registration.client_secret?.trim() : void 0;
|
|
3509
|
+
if (registration.client_id.trim() !== client.clientId || registeredSecret !== client.clientSecret)
|
|
3510
|
+
throw new Error("OAuth client registration does not match the client identity");
|
|
3511
|
+
client.registration = registration;
|
|
3512
|
+
}
|
|
3513
|
+
return client;
|
|
3514
|
+
}
|
|
3515
|
+
|
|
3398
3516
|
// ../mcp-oauth/dist/client/auth-store-session-store.js
|
|
3399
3517
|
import crypto from "node:crypto";
|
|
3400
3518
|
import path4 from "node:path";
|
|
@@ -4128,14 +4246,8 @@ function createAuthStoreClientStore(options, namespace) {
|
|
|
4128
4246
|
} catch {
|
|
4129
4247
|
throw new Error("Stored OAuth client must be valid JSON; reset the store explicitly to recover");
|
|
4130
4248
|
}
|
|
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
|
-
}
|
|
4249
|
+
if (isObjectRecord(parsed) && typeof getOwnEntry3(parsed, "clientId") === "string")
|
|
4250
|
+
return parsed;
|
|
4139
4251
|
throw new Error("Stored OAuth client must be a JSON object with clientId");
|
|
4140
4252
|
},
|
|
4141
4253
|
async save(issuer, client) {
|
|
@@ -4201,14 +4313,7 @@ function isStoredOAuthSession(value) {
|
|
|
4201
4313
|
if (!isObjectRecord(value)) {
|
|
4202
4314
|
return false;
|
|
4203
4315
|
}
|
|
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;
|
|
4316
|
+
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
4317
|
}
|
|
4213
4318
|
function isStoredOAuthDiscovery(value) {
|
|
4214
4319
|
if (!isObjectRecord(value)) {
|
|
@@ -4242,16 +4347,6 @@ function isNonBlankOwnString(record2, key2) {
|
|
|
4242
4347
|
return value !== void 0 && value.trim().length > 0;
|
|
4243
4348
|
}
|
|
4244
4349
|
|
|
4245
|
-
// ../mcp-oauth/dist/client/scope.js
|
|
4246
|
-
function normalizeOAuthScope(scope) {
|
|
4247
|
-
if (scope === void 0)
|
|
4248
|
-
return void 0;
|
|
4249
|
-
if (typeof scope !== "string" || [...scope].some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) > 126 || char === '"' || char === "\\"))
|
|
4250
|
-
throw new Error("Invalid OAuth scope syntax");
|
|
4251
|
-
const normalized = [...new Set(scope.split(" ").filter(Boolean))].sort().join(" ");
|
|
4252
|
-
return normalized || void 0;
|
|
4253
|
-
}
|
|
4254
|
-
|
|
4255
4350
|
// ../mcp-oauth/dist/client/default-oauth-client-provider.js
|
|
4256
4351
|
import { isIP } from "node:net";
|
|
4257
4352
|
|
|
@@ -4861,6 +4956,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4861
4956
|
assertPersistenceNamespace(options.persistenceNamespace);
|
|
4862
4957
|
const clientMetadata = getClientMetadata(options.client);
|
|
4863
4958
|
const requestedScope = clientMetadata?.scope;
|
|
4959
|
+
const configuredClient = normalizeConfiguredClient(options.client);
|
|
4864
4960
|
const sessionStore = options.sessionStore ?? createAuthStoreSessionStore(options.authStore, options.persistenceNamespace);
|
|
4865
4961
|
const clientStore = options.authStore === void 0 ? null : createAuthStoreClientStore(options.authStore, options.persistenceNamespace);
|
|
4866
4962
|
const now = options.now ?? Date.now;
|
|
@@ -4878,7 +4974,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4878
4974
|
const initialGrant = options.initialGrant === void 0 ? void 0 : {
|
|
4879
4975
|
resource: canonicalizeResourceIndicator(options.initialGrant.resource),
|
|
4880
4976
|
tokens: normalizeStoredTokens(options.initialGrant.tokens),
|
|
4881
|
-
client:
|
|
4977
|
+
client: configuredClient
|
|
4882
4978
|
};
|
|
4883
4979
|
if (initialGrant !== void 0 && (initialGrant.tokens === void 0 || initialGrant.client === null))
|
|
4884
4980
|
throw new Error("OAuth initial grant requires valid tokens and the original client ID");
|
|
@@ -4982,8 +5078,8 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4982
5078
|
if (forceRefresh && rejectedTokens !== void 0 && (rejectedTokens === null || session?.tokens === void 0 || !sameTokenGrant(session.tokens, rejectedTokens)))
|
|
4983
5079
|
forceRefresh = false;
|
|
4984
5080
|
const sessionDiscovery = resolveDiscovery(discovery, session);
|
|
4985
|
-
if ((options.client.mode === "static" || initialGrant !== void 0) && session !== null && (session.tokens !== void 0 || session.refreshState === "pending")) {
|
|
4986
|
-
const configured =
|
|
5081
|
+
if ((options.client.mode === "static" || configuredClient?.registration !== void 0 || initialGrant !== void 0) && session !== null && (session.tokens !== void 0 || session.refreshState === "pending")) {
|
|
5082
|
+
const configured = configuredClient;
|
|
4987
5083
|
if (configured === null || configured.clientId !== session.client.clientId || configured.clientSecret !== session.client.clientSecret)
|
|
4988
5084
|
throw new Error("Stored session belongs to a different OAuth client; use separate persistence or explicitly reset it");
|
|
4989
5085
|
}
|
|
@@ -5157,8 +5253,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5157
5253
|
}
|
|
5158
5254
|
async function resolveClient(existingSession, discovery, redirectUri, fetch2, parentSignal) {
|
|
5159
5255
|
parentSignal?.throwIfAborted();
|
|
5160
|
-
|
|
5161
|
-
if (options.client.mode === "static") {
|
|
5256
|
+
if (options.client.mode === "static" || configuredClient?.registration !== void 0) {
|
|
5162
5257
|
if (configuredClient === null) {
|
|
5163
5258
|
throw new Error("OAuth client_id must not be blank");
|
|
5164
5259
|
}
|
|
@@ -5217,14 +5312,12 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5217
5312
|
signal
|
|
5218
5313
|
});
|
|
5219
5314
|
const payload = await readOAuthJsonObjectResponse(response, signal);
|
|
5220
|
-
const
|
|
5221
|
-
|
|
5222
|
-
throw new Error("OAuth client registration response missing client_id");
|
|
5223
|
-
}
|
|
5224
|
-
const clientSecret = getOwnString2(payload, "client_secret");
|
|
5315
|
+
const registration = parseOAuthClientRegistration(payload);
|
|
5316
|
+
const registeredSecret = getOwnString2(registration, "client_secret");
|
|
5225
5317
|
const registeredClient = {
|
|
5226
|
-
clientId:
|
|
5227
|
-
|
|
5318
|
+
clientId: registration.client_id.trim(),
|
|
5319
|
+
...registeredSecret === void 0 ? {} : { clientSecret: registeredSecret.trim() },
|
|
5320
|
+
registration
|
|
5228
5321
|
};
|
|
5229
5322
|
await saveRegisteredClient(discovery.authorizationServer, registeredClient);
|
|
5230
5323
|
return {
|
|
@@ -5250,7 +5343,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5250
5343
|
return null;
|
|
5251
5344
|
}
|
|
5252
5345
|
const client = await clientStore.load(issuer);
|
|
5253
|
-
const normalizedClient = client === null ? null :
|
|
5346
|
+
const normalizedClient = client === null ? null : normalizeStoredOAuthClient(client);
|
|
5254
5347
|
if (client !== null && normalizedClient === null) {
|
|
5255
5348
|
await clientStore.clear(issuer);
|
|
5256
5349
|
return null;
|
|
@@ -5323,7 +5416,7 @@ function normalizeLoadedSession(session) {
|
|
|
5323
5416
|
const refreshState = getOwnEntry6(session, "refreshState");
|
|
5324
5417
|
if (refreshState !== void 0 && (refreshState !== "pending" || getOwnEntry6(session, "tokens") !== void 0))
|
|
5325
5418
|
throw new Error("Stored OAuth refresh state is invalid");
|
|
5326
|
-
const client =
|
|
5419
|
+
const client = normalizeStoredOAuthClient(getOwnEntry6(session, "client"));
|
|
5327
5420
|
if (client === null) {
|
|
5328
5421
|
return { ...session, client: { clientId: "" }, tokens: void 0 };
|
|
5329
5422
|
}
|
|
@@ -5333,25 +5426,6 @@ function normalizeLoadedSession(session) {
|
|
|
5333
5426
|
tokens: normalizeStoredTokens(getOwnEntry6(session, "tokens"))
|
|
5334
5427
|
};
|
|
5335
5428
|
}
|
|
5336
|
-
function normalizeStoredClient(value) {
|
|
5337
|
-
if (!isObjectRecord3(value)) {
|
|
5338
|
-
return null;
|
|
5339
|
-
}
|
|
5340
|
-
const clientId = getOwnString2(value, "clientId");
|
|
5341
|
-
if (clientId === void 0 || clientId.trim().length === 0) {
|
|
5342
|
-
return null;
|
|
5343
|
-
}
|
|
5344
|
-
const normalizedClientId = clientId.trim();
|
|
5345
|
-
const clientSecret = getOwnEntry6(value, "clientSecret");
|
|
5346
|
-
if (clientSecret === void 0) {
|
|
5347
|
-
return { clientId: normalizedClientId };
|
|
5348
|
-
}
|
|
5349
|
-
if (typeof clientSecret !== "string" || clientSecret.trim().length === 0) {
|
|
5350
|
-
return null;
|
|
5351
|
-
}
|
|
5352
|
-
const normalizedClientSecret = clientSecret.trim();
|
|
5353
|
-
return { clientId: normalizedClientId, clientSecret: normalizedClientSecret };
|
|
5354
|
-
}
|
|
5355
5429
|
function normalizeStoredTokens(value) {
|
|
5356
5430
|
if (value === void 0 || !isObjectRecord3(value)) {
|
|
5357
5431
|
return void 0;
|
|
@@ -5387,12 +5461,12 @@ function getClientMetadata(client) {
|
|
|
5387
5461
|
};
|
|
5388
5462
|
}
|
|
5389
5463
|
function normalizeConfiguredClient(client) {
|
|
5390
|
-
const
|
|
5391
|
-
|
|
5464
|
+
const registration = client.registration === void 0 ? void 0 : parseOAuthClientRegistration(client.registration);
|
|
5465
|
+
const clientId = normalizeOptionalOAuthString(client.clientId) ?? registration?.client_id.trim();
|
|
5466
|
+
if (clientId === void 0)
|
|
5392
5467
|
return null;
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
return clientSecret === void 0 ? { clientId } : { clientId, clientSecret };
|
|
5468
|
+
const clientSecret = normalizeOptionalOAuthString(client.clientSecret) ?? (registration === void 0 ? void 0 : getOwnString2(registration, "client_secret")?.trim());
|
|
5469
|
+
return normalizeStoredOAuthClient({ clientId, clientSecret, registration });
|
|
5396
5470
|
}
|
|
5397
5471
|
function normalizeOptionalOAuthString(value) {
|
|
5398
5472
|
if (value === void 0) {
|