@frontmcp/auth 1.8.2 → 1.8.4
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/authorities/authorities.engine.d.ts +25 -2
- package/authorities/authorities.engine.d.ts.map +1 -1
- package/authorities/authorities.validation.d.ts +27 -0
- package/authorities/authorities.validation.d.ts.map +1 -0
- package/authorities/index.d.ts +1 -0
- package/authorities/index.d.ts.map +1 -1
- package/authorization/dcr-client.registry.d.ts +13 -0
- package/authorization/dcr-client.registry.d.ts.map +1 -1
- package/esm/index.mjs +530 -91
- package/esm/package.json +5 -5
- package/index.d.ts +4 -4
- package/index.d.ts.map +1 -1
- package/index.js +615 -166
- package/jwks/jwks.service.d.ts +4 -1
- package/jwks/jwks.service.d.ts.map +1 -1
- package/options/app-auth.schema.d.ts +4 -0
- package/options/app-auth.schema.d.ts.map +1 -1
- package/options/interfaces.d.ts +48 -7
- package/options/interfaces.d.ts.map +1 -1
- package/options/orchestrated.schema.d.ts +8 -0
- package/options/orchestrated.schema.d.ts.map +1 -1
- package/options/schema.d.ts +4 -0
- package/options/schema.d.ts.map +1 -1
- package/options/shared.schemas.d.ts +2 -0
- package/options/shared.schemas.d.ts.map +1 -1
- package/package.json +5 -5
- package/session/authorization.store.d.ts +19 -3
- package/session/authorization.store.d.ts.map +1 -1
- package/session/federated-auth.session.d.ts +16 -0
- package/session/federated-auth.session.d.ts.map +1 -1
- package/session/index.d.ts +4 -0
- package/session/index.d.ts.map +1 -1
- package/session/pending-login.d.ts +23 -0
- package/session/pending-login.d.ts.map +1 -0
- package/session/signin-binding.d.ts +39 -0
- package/session/signin-binding.d.ts.map +1 -0
- package/ui/base-layout.d.ts +26 -0
- package/ui/base-layout.d.ts.map +1 -1
- package/ui/index.d.ts +2 -2
- package/ui/index.d.ts.map +1 -1
- package/ui/local-login.helper.d.ts +9 -2
- package/ui/local-login.helper.d.ts.map +1 -1
- package/ui/templates.d.ts +5 -4
- package/ui/templates.d.ts.map +1 -1
- package/utils/index.d.ts +2 -0
- package/utils/index.d.ts.map +1 -1
- package/utils/redirect-uri.utils.d.ts +16 -0
- package/utils/redirect-uri.utils.d.ts.map +1 -0
- package/utils/scope-grant.utils.d.ts +21 -0
- package/utils/scope-grant.utils.d.ts.map +1 -0
package/index.js
CHANGED
|
@@ -248,6 +248,7 @@ __export(index_exports, {
|
|
|
248
248
|
AuthoritiesProfileRegistry: () => AuthoritiesProfileRegistry,
|
|
249
249
|
AuthorityDeniedError: () => AuthorityDeniedError,
|
|
250
250
|
AuthorizationBase: () => AuthorizationBase,
|
|
251
|
+
BUILT_IN_AUTH_PAGE_CSP: () => BUILT_IN_AUTH_PAGE_CSP,
|
|
251
252
|
CDN: () => CDN,
|
|
252
253
|
CREDENTIALS_ACCESSOR: () => CREDENTIALS_ACCESSOR,
|
|
253
254
|
CimdClientIdMismatchError: () => CimdClientIdMismatchError,
|
|
@@ -262,6 +263,7 @@ __export(index_exports, {
|
|
|
262
263
|
CredentialProviderAlreadyRegisteredError: () => CredentialProviderAlreadyRegisteredError,
|
|
263
264
|
CredentialStorageError: () => CredentialStorageError,
|
|
264
265
|
CredentialsAccessorImpl: () => CredentialsAccessorImpl,
|
|
266
|
+
DEFAULT_ALLOWED_SCOPES: () => DEFAULT_ALLOWED_SCOPES,
|
|
265
267
|
DEFAULT_INCREMENTAL_TICKET_TTL_MS: () => DEFAULT_INCREMENTAL_TICKET_TTL_MS,
|
|
266
268
|
DEFAULT_RESUME_TTL_MS: () => DEFAULT_RESUME_TTL_MS,
|
|
267
269
|
DEFAULT_THEME: () => DEFAULT_THEME,
|
|
@@ -269,9 +271,9 @@ __export(index_exports, {
|
|
|
269
271
|
EagerCredentialLoader: () => EagerCredentialLoader,
|
|
270
272
|
ElicitationSecretRequiredError: () => ElicitationSecretRequiredError,
|
|
271
273
|
EncryptedRedisVault: () => EncryptedRedisVault,
|
|
272
|
-
EncryptedStorageError: () =>
|
|
274
|
+
EncryptedStorageError: () => import_utils26.EncryptedStorageError,
|
|
273
275
|
EncryptedStorageSecureStoreBackend: () => EncryptedStorageSecureStoreBackend,
|
|
274
|
-
EncryptedTypedStorage: () =>
|
|
276
|
+
EncryptedTypedStorage: () => import_utils26.EncryptedTypedStorage,
|
|
275
277
|
EncryptionContextNotSetError: () => EncryptionContextNotSetError,
|
|
276
278
|
EncryptionKeyNotConfiguredError: () => EncryptionKeyNotConfiguredError,
|
|
277
279
|
FetchCredentialMiddleware: () => FetchCredentialMiddleware,
|
|
@@ -300,6 +302,9 @@ __export(index_exports, {
|
|
|
300
302
|
RedisAuthorizationStore: () => RedisAuthorizationStore,
|
|
301
303
|
RedisSessionStore: () => RedisSessionStore,
|
|
302
304
|
SECURE_STORE_ACCESSOR: () => SECURE_STORE_ACCESSOR,
|
|
305
|
+
SIGNIN_BINDING_COOKIE_PREFIX: () => SIGNIN_BINDING_COOKIE_PREFIX,
|
|
306
|
+
SIGNIN_BINDING_MAX_AGE_SECONDS: () => SIGNIN_BINDING_MAX_AGE_SECONDS,
|
|
307
|
+
SIGNIN_BINDING_SECURE_COOKIE_PREFIX: () => SIGNIN_BINDING_SECURE_COOKIE_PREFIX,
|
|
303
308
|
ScopeDeniedError: () => ScopeDeniedError,
|
|
304
309
|
SecureStoreAccessorImpl: () => SecureStoreAccessorImpl,
|
|
305
310
|
SessionCredentialVault: () => SessionCredentialVault,
|
|
@@ -319,7 +324,7 @@ __export(index_exports, {
|
|
|
319
324
|
TokenVault: () => TokenVault,
|
|
320
325
|
TransparentAuthorization: () => TransparentAuthorization,
|
|
321
326
|
TransportIdGenerator: () => TransportIdGenerator,
|
|
322
|
-
TypedStorage: () =>
|
|
327
|
+
TypedStorage: () => import_utils25.TypedStorage,
|
|
323
328
|
VaultEncryption: () => VaultEncryption,
|
|
324
329
|
VaultLoadError: () => VaultLoadError,
|
|
325
330
|
VaultNotFoundError: () => VaultNotFoundError,
|
|
@@ -327,6 +332,7 @@ __export(index_exports, {
|
|
|
327
332
|
abacConditionSchema: () => abacConditionSchema,
|
|
328
333
|
abacOperatorSchema: () => abacOperatorSchema,
|
|
329
334
|
abacPolicySchema: () => abacPolicySchema,
|
|
335
|
+
advertisedScopes: () => advertisedScopes,
|
|
330
336
|
aiPlatformTypeSchema: () => aiPlatformTypeSchema,
|
|
331
337
|
allowsPublicAccess: () => allowsPublicAccess,
|
|
332
338
|
apiKeyCredentialSchema: () => apiKeyCredentialSchema,
|
|
@@ -375,6 +381,7 @@ __export(index_exports, {
|
|
|
375
381
|
buildToolConsentPage: () => buildToolConsentPage,
|
|
376
382
|
buildUnauthorizedHeader: () => buildUnauthorizedHeader,
|
|
377
383
|
buildWwwAuthenticate: () => buildWwwAuthenticate,
|
|
384
|
+
builtInAuthPageHeaders: () => builtInAuthPageHeaders,
|
|
378
385
|
centeredCardLayout: () => centeredCardLayout,
|
|
379
386
|
checkSsrfProtection: () => checkSsrfProtection,
|
|
380
387
|
cimdCacheConfigSchema: () => cimdCacheConfigSchema,
|
|
@@ -394,6 +401,7 @@ __export(index_exports, {
|
|
|
394
401
|
createLayout: () => createLayout,
|
|
395
402
|
createSecureStore: () => createSecureStore,
|
|
396
403
|
createSessionCredentialVault: () => createSessionCredentialVault,
|
|
404
|
+
createSigninBinding: () => createSigninBinding,
|
|
397
405
|
createTokenStorageAdapter: () => createTokenStorageAdapter,
|
|
398
406
|
credentialProviderConfigSchema: () => credentialProviderConfigSchema,
|
|
399
407
|
credentialSchema: () => credentialSchema,
|
|
@@ -401,9 +409,9 @@ __export(index_exports, {
|
|
|
401
409
|
credentialTypeSchema: () => credentialTypeSchema,
|
|
402
410
|
customCredentialSchema: () => customCredentialSchema,
|
|
403
411
|
decodeJwtPayloadSafe: () => decodeJwtPayloadSafe,
|
|
404
|
-
decryptAesGcm: () =>
|
|
412
|
+
decryptAesGcm: () => import_utils36.decryptAesGcm,
|
|
405
413
|
decryptSessionJson: () => decryptSessionJson,
|
|
406
|
-
decryptValue: () =>
|
|
414
|
+
decryptValue: () => import_utils36.decryptValue,
|
|
407
415
|
defaultSessionRateLimiter: () => defaultSessionRateLimiter,
|
|
408
416
|
deriveAuthorizationId: () => deriveAuthorizationId,
|
|
409
417
|
deriveExpectedAudience: () => deriveExpectedAudience,
|
|
@@ -411,9 +419,9 @@ __export(index_exports, {
|
|
|
411
419
|
deriveTypedUser: () => deriveTypedUser,
|
|
412
420
|
detectAuthProviders: () => detectAuthProviders,
|
|
413
421
|
detectedAuthProviderSchema: () => detectedAuthProviderSchema,
|
|
414
|
-
encryptAesGcm: () =>
|
|
422
|
+
encryptAesGcm: () => import_utils36.encryptAesGcm,
|
|
415
423
|
encryptJson: () => encryptJson,
|
|
416
|
-
encryptValue: () =>
|
|
424
|
+
encryptValue: () => import_utils36.encryptValue,
|
|
417
425
|
encryptedBlobSchema: () => encryptedBlobSchema,
|
|
418
426
|
encryptedDataSchema: () => encryptedDataSchema,
|
|
419
427
|
encryptedVaultEntrySchema: () => encryptedVaultEntrySchema,
|
|
@@ -426,6 +434,8 @@ __export(index_exports, {
|
|
|
426
434
|
federatedLoginStateSchema: () => federatedLoginStateSchema,
|
|
427
435
|
federatedProviderItemSchema: () => federatedProviderItemSchema,
|
|
428
436
|
federatedSelectionSchema: () => federatedSelectionSchema,
|
|
437
|
+
findAuthoritiesProfileProblems: () => findAuthoritiesProfileProblems,
|
|
438
|
+
findAuthoritiesRuleProblems: () => findAuthoritiesRuleProblems,
|
|
429
439
|
flatRemoteProviderFields: () => flatRemoteProviderFields,
|
|
430
440
|
fromSessionRecord: () => fromSessionRecord,
|
|
431
441
|
generateAuthorizationCode: () => generateAuthorizationCode,
|
|
@@ -437,15 +447,17 @@ __export(index_exports, {
|
|
|
437
447
|
getProviderApps: () => getProviderApps,
|
|
438
448
|
getProviderScopes: () => getProviderScopes,
|
|
439
449
|
getTokenSignatureFingerprint: () => getTokenSignatureFingerprint,
|
|
450
|
+
grantScopes: () => grantScopes,
|
|
440
451
|
hasOnlyLocalhostRedirectUris: () => hasOnlyLocalhostRedirectUris,
|
|
441
452
|
headerApplier: () => headerApplier,
|
|
442
|
-
hkdfSha256: () =>
|
|
453
|
+
hkdfSha256: () => import_utils36.hkdfSha256,
|
|
443
454
|
incrementalAuthConfigSchema: () => incrementalAuthConfigSchema,
|
|
444
455
|
isAnonymousSubject: () => isAnonymousSubject,
|
|
445
456
|
isCimdClientId: () => isCimdClientId,
|
|
446
457
|
isFrontMcpCredentials: () => isFrontMcpCredentials,
|
|
447
458
|
isJwt: () => isJwt,
|
|
448
459
|
isLocalMode: () => isLocalMode,
|
|
460
|
+
isLoopbackRedirectUri: () => isLoopbackRedirectUri,
|
|
449
461
|
isOrchestratedLocal: () => isOrchestratedLocal,
|
|
450
462
|
isOrchestratedMode: () => isOrchestratedMode,
|
|
451
463
|
isOrchestratedRemote: () => isOrchestratedRemote,
|
|
@@ -454,7 +466,7 @@ __export(index_exports, {
|
|
|
454
466
|
isRedisTokenStorage: () => isRedisTokenStorage,
|
|
455
467
|
isRemoteMode: () => isRemoteMode,
|
|
456
468
|
isSessionComplete: () => isSessionComplete,
|
|
457
|
-
isSignedSession: () =>
|
|
469
|
+
isSignedSession: () => import_utils18.isSignedData,
|
|
458
470
|
isSoonExpiring: () => isSoonExpiring,
|
|
459
471
|
isSoonExpiringProvider: () => isSoonExpiringProvider,
|
|
460
472
|
isSqliteTokenStorage: () => isSqliteTokenStorage,
|
|
@@ -475,6 +487,7 @@ __export(index_exports, {
|
|
|
475
487
|
noopLogger: () => noopLogger,
|
|
476
488
|
normalizeIssuer: () => normalizeIssuer,
|
|
477
489
|
oauthCredentialSchema: () => oauthCredentialSchema,
|
|
490
|
+
openPendingLogin: () => openPendingLogin,
|
|
478
491
|
orchestratedLocalSchema: () => orchestratedLocalSchema,
|
|
479
492
|
orchestratedRemoteSchema: () => orchestratedRemoteSchema,
|
|
480
493
|
parseAuthOptions: () => parseAuthOptions,
|
|
@@ -502,6 +515,7 @@ __export(index_exports, {
|
|
|
502
515
|
resolveRequiredScopes: () => resolveRequiredScopes,
|
|
503
516
|
resourceIdRefSchema: () => resourceIdRefSchema,
|
|
504
517
|
safeDecrypt: () => safeDecrypt,
|
|
518
|
+
sealPendingLogin: () => sealPendingLogin,
|
|
505
519
|
secureStoreConfigSchema: () => secureStoreConfigSchema,
|
|
506
520
|
secureStoreCustomBackendSchema: () => secureStoreCustomBackendSchema,
|
|
507
521
|
secureStoreEncryptionSchema: () => secureStoreEncryptionSchema,
|
|
@@ -512,6 +526,8 @@ __export(index_exports, {
|
|
|
512
526
|
signCredentialResumeToken: () => signCredentialResumeToken,
|
|
513
527
|
signIncrementalAuthTicket: () => signIncrementalAuthTicket,
|
|
514
528
|
signSession: () => signSession,
|
|
529
|
+
signinBindingCookieName: () => signinBindingCookieName,
|
|
530
|
+
signinBindingMatches: () => signinBindingMatches,
|
|
515
531
|
skippedAppBehaviorSchema: () => skippedAppBehaviorSchema,
|
|
516
532
|
sseTransportStateSchema: () => sseTransportStateSchema,
|
|
517
533
|
sshKeyCredentialSchema: () => sshKeyCredentialSchema,
|
|
@@ -544,7 +560,8 @@ __export(index_exports, {
|
|
|
544
560
|
verifyOrParseSession: () => verifyOrParseSession,
|
|
545
561
|
verifyPkce: () => verifyPkce,
|
|
546
562
|
verifySession: () => verifySession,
|
|
547
|
-
wideLayout: () => wideLayout
|
|
563
|
+
wideLayout: () => wideLayout,
|
|
564
|
+
withoutSecretFieldValues: () => withoutSecretFieldValues
|
|
548
565
|
});
|
|
549
566
|
module.exports = __toCommonJS(index_exports);
|
|
550
567
|
|
|
@@ -941,6 +958,12 @@ var TRANSPARENT_JWT_ALGS = [
|
|
|
941
958
|
];
|
|
942
959
|
var MAX_JWKS_FETCH_BYTES = 1048576;
|
|
943
960
|
var MAX_JWKS_FETCH_HOPS = 3;
|
|
961
|
+
var MISSING_EXP_ERROR = 'missing required "exp" claim';
|
|
962
|
+
function isMissingExpError(error) {
|
|
963
|
+
if (typeof error !== "object" || error === null) return false;
|
|
964
|
+
const { code, claim, reason } = error;
|
|
965
|
+
return code === "ERR_JWT_CLAIM_VALIDATION_FAILED" && claim === "exp" && reason === "missing";
|
|
966
|
+
}
|
|
944
967
|
var WEAK_KEY_WARNING = `
|
|
945
968
|
\u26A0\uFE0F SECURITY WARNING: OAuth provider is using an RSA key smaller than 2048 bits.
|
|
946
969
|
This is considered insecure and should be updated.
|
|
@@ -1010,6 +1033,7 @@ var JwksService = class {
|
|
|
1010
1033
|
kid = typeof header?.kid === "string" ? header.kid : void 0;
|
|
1011
1034
|
} catch {
|
|
1012
1035
|
}
|
|
1036
|
+
let missingExp = false;
|
|
1013
1037
|
for (const p of candidates) {
|
|
1014
1038
|
let jwks;
|
|
1015
1039
|
try {
|
|
@@ -1021,7 +1045,9 @@ var JwksService = class {
|
|
|
1021
1045
|
// Pin to asymmetric algorithms so a symmetric key in the provider JWKS
|
|
1022
1046
|
// can't be used to accept an HMAC-signed token, and `none` is refused.
|
|
1023
1047
|
algorithms: [...TRANSPARENT_JWT_ALGS],
|
|
1024
|
-
...issuerConstraint ? { issuer: issuerConstraint } : {}
|
|
1048
|
+
...issuerConstraint ? { issuer: issuerConstraint } : {},
|
|
1049
|
+
// A bearer token without `exp` would be valid forever (#272).
|
|
1050
|
+
requiredClaims: ["exp"]
|
|
1025
1051
|
});
|
|
1026
1052
|
return {
|
|
1027
1053
|
ok: true,
|
|
@@ -1039,11 +1065,14 @@ var JwksService = class {
|
|
|
1039
1065
|
if (fallbackResult.ok) {
|
|
1040
1066
|
return fallbackResult;
|
|
1041
1067
|
}
|
|
1068
|
+
if (fallbackResult.error === "missing_exp") missingExp = true;
|
|
1042
1069
|
}
|
|
1043
1070
|
}
|
|
1071
|
+
if (isMissingExpError(e)) missingExp = true;
|
|
1044
1072
|
this.logger.debug("[JwksService] Failed to verify token for provider: %s", p.id, e);
|
|
1045
1073
|
}
|
|
1046
1074
|
}
|
|
1075
|
+
if (missingExp) return { ok: false, error: MISSING_EXP_ERROR };
|
|
1047
1076
|
return { ok: false, error: `no_provider_verified${kid ? ` (kid=${kid})` : ""}` };
|
|
1048
1077
|
}
|
|
1049
1078
|
/**
|
|
@@ -1124,7 +1153,10 @@ var JwksService = class {
|
|
|
1124
1153
|
}
|
|
1125
1154
|
}
|
|
1126
1155
|
const nowSec = Math.floor(Date.now() / 1e3);
|
|
1127
|
-
if (payload.exp
|
|
1156
|
+
if (payload.exp === void 0) {
|
|
1157
|
+
return { ok: false, error: "missing_exp" };
|
|
1158
|
+
}
|
|
1159
|
+
if (typeof payload.exp !== "number" || !Number.isFinite(payload.exp) || payload.exp <= nowSec) {
|
|
1128
1160
|
return { ok: false, error: "token_expired" };
|
|
1129
1161
|
}
|
|
1130
1162
|
if (payload.nbf !== void 0 && (typeof payload.nbf !== "number" || !Number.isFinite(payload.nbf) || payload.nbf > nowSec)) {
|
|
@@ -1173,7 +1205,10 @@ var JwksService = class {
|
|
|
1173
1205
|
* 1) inline jwks (if provided) → cache & return
|
|
1174
1206
|
* 2) cached & fresh (TTL) → return
|
|
1175
1207
|
* 3) explicit jwksUri → fetch, cache, return
|
|
1176
|
-
* 4) discover jwks_uri
|
|
1208
|
+
* 4) discover jwks_uri → the issuer's OAuth authorization server
|
|
1209
|
+
* metadata (RFC 8414), else its OpenID configuration (OpenID Connect
|
|
1210
|
+
* Discovery 1.0 §4, where Google, Okta, Auth0 and Entra publish it),
|
|
1211
|
+
* then fetch jwks_uri, cache, return
|
|
1177
1212
|
*/
|
|
1178
1213
|
async getJwksForProvider(ref) {
|
|
1179
1214
|
if (ref.jwks?.keys?.length) {
|
|
@@ -1189,11 +1224,13 @@ var JwksService = class {
|
|
|
1189
1224
|
if (fromUri?.keys?.length) return fromUri;
|
|
1190
1225
|
}
|
|
1191
1226
|
const issuer = trimSlash(ref.issuerUrl);
|
|
1192
|
-
const
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1227
|
+
for (const document of ["oauth-authorization-server", "openid-configuration"]) {
|
|
1228
|
+
const meta = await this.tryFetchAsMeta(`${issuer}/.well-known/${document}`);
|
|
1229
|
+
const uri = meta && typeof meta === "object" && meta["jwks_uri"] ? String(meta["jwks_uri"]) : void 0;
|
|
1230
|
+
if (uri) {
|
|
1231
|
+
const fromMeta = await this.tryFetchJwks(ref.id, uri);
|
|
1232
|
+
if (fromMeta?.keys?.length) return fromMeta;
|
|
1233
|
+
}
|
|
1197
1234
|
}
|
|
1198
1235
|
const maxStaleMs = Math.max(this.opts.providerJwksTtlMs * 4, 6e4);
|
|
1199
1236
|
if (cached && Date.now() - cached.fetchedAt < maxStaleMs) {
|
|
@@ -1380,6 +1417,26 @@ var CDN = {
|
|
|
1380
1417
|
stylesheet: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
|
|
1381
1418
|
}
|
|
1382
1419
|
};
|
|
1420
|
+
var BUILT_IN_AUTH_PAGE_CSP = [
|
|
1421
|
+
"default-src 'self'",
|
|
1422
|
+
"script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net",
|
|
1423
|
+
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
|
|
1424
|
+
"font-src 'self' https://fonts.gstatic.com",
|
|
1425
|
+
"img-src 'self' data: https:",
|
|
1426
|
+
"connect-src 'self'",
|
|
1427
|
+
"object-src 'none'",
|
|
1428
|
+
"base-uri 'none'",
|
|
1429
|
+
"frame-ancestors 'none'"
|
|
1430
|
+
].join("; ");
|
|
1431
|
+
function builtInAuthPageHeaders(options = {}) {
|
|
1432
|
+
return {
|
|
1433
|
+
...options.csp === false ? {} : { "Content-Security-Policy": BUILT_IN_AUTH_PAGE_CSP },
|
|
1434
|
+
"X-Frame-Options": "DENY",
|
|
1435
|
+
"X-Content-Type-Options": "nosniff",
|
|
1436
|
+
"Referrer-Policy": "same-origin",
|
|
1437
|
+
"Cache-Control": "no-store"
|
|
1438
|
+
};
|
|
1439
|
+
}
|
|
1383
1440
|
var DEFAULT_THEME = {
|
|
1384
1441
|
colors: {
|
|
1385
1442
|
primary: "#3b82f6",
|
|
@@ -1617,7 +1674,7 @@ function buildIncrementalAuthPage(params) {
|
|
|
1617
1674
|
</div>
|
|
1618
1675
|
</div>
|
|
1619
1676
|
|
|
1620
|
-
<form method="
|
|
1677
|
+
<form method="POST" action="${escapeHtml3(callbackPath)}" class="flex gap-3 pt-4 border-t border-gray-100">
|
|
1621
1678
|
<input type="hidden" name="pending_auth_id" value="${escapeHtml3(sessionHint)}">
|
|
1622
1679
|
<button type="button" onclick="window.close()"
|
|
1623
1680
|
class="flex-1 px-4 py-2.5 text-gray-600 hover:text-gray-900 hover:bg-gray-100 font-medium rounded-lg transition-colors">
|
|
@@ -1663,7 +1720,7 @@ function buildFederatedLoginPage(params) {
|
|
|
1663
1720
|
${escapeHtml3(clientName)} uses multiple authentication providers. Select which ones you want to authorize.
|
|
1664
1721
|
</p>
|
|
1665
1722
|
|
|
1666
|
-
<form method="
|
|
1723
|
+
<form method="POST" action="${escapeHtml3(callbackPath)}" id="federated-form">
|
|
1667
1724
|
<input type="hidden" name="pending_auth_id" value="${escapeHtml3(pendingAuthId)}">
|
|
1668
1725
|
<input type="hidden" name="federated" value="true">
|
|
1669
1726
|
|
|
@@ -1808,7 +1865,7 @@ function buildToolConsentPage(params) {
|
|
|
1808
1865
|
${errorBanner}
|
|
1809
1866
|
${userInfo}
|
|
1810
1867
|
|
|
1811
|
-
<form method="
|
|
1868
|
+
<form method="POST" action="${escapeHtml3(callbackPath)}" id="consent-form">
|
|
1812
1869
|
<input type="hidden" name="csrf" value="${escapeHtml3(csrfToken)}">
|
|
1813
1870
|
<input type="hidden" name="pending_auth_id" value="${escapeHtml3(pendingAuthId)}">
|
|
1814
1871
|
<input type="hidden" name="consent_submitted" value="1">
|
|
@@ -1906,7 +1963,7 @@ function buildLoginPage(params) {
|
|
|
1906
1963
|
|
|
1907
1964
|
${scopesHtml}
|
|
1908
1965
|
|
|
1909
|
-
<form method="
|
|
1966
|
+
<form method="POST" action="${escapeHtml3(callbackPath)}">
|
|
1910
1967
|
<input type="hidden" name="pending_auth_id" value="${escapeHtml3(pendingAuthId)}">
|
|
1911
1968
|
${fieldsHtml}
|
|
1912
1969
|
|
|
@@ -2003,7 +2060,17 @@ function toLoginExtraFields(fields, values) {
|
|
|
2003
2060
|
value: values?.[name]
|
|
2004
2061
|
}));
|
|
2005
2062
|
}
|
|
2006
|
-
function
|
|
2063
|
+
function withoutSecretFieldValues(values, fields) {
|
|
2064
|
+
if (!values) return void 0;
|
|
2065
|
+
const kept = {};
|
|
2066
|
+
for (const [name, value] of Object.entries(values)) {
|
|
2067
|
+
if (fields?.[name]?.type === "password") continue;
|
|
2068
|
+
kept[name] = value;
|
|
2069
|
+
}
|
|
2070
|
+
return kept;
|
|
2071
|
+
}
|
|
2072
|
+
function renderLocalLoginPage(login, ctx, submitted) {
|
|
2073
|
+
const values = withoutSecretFieldValues(submitted, login?.fields);
|
|
2007
2074
|
if (login?.render) {
|
|
2008
2075
|
return login.render({ ...ctx, values });
|
|
2009
2076
|
}
|
|
@@ -2110,7 +2177,8 @@ function buildPendingRecord(params) {
|
|
|
2110
2177
|
priorAuthorizedAppIds: params.priorAuthorizedAppIds,
|
|
2111
2178
|
federatedLogin: params.federatedLogin,
|
|
2112
2179
|
consent: params.consent,
|
|
2113
|
-
authUiCsrf: params.authUiCsrf
|
|
2180
|
+
authUiCsrf: params.authUiCsrf,
|
|
2181
|
+
signinBinding: params.signinBinding
|
|
2114
2182
|
};
|
|
2115
2183
|
}
|
|
2116
2184
|
function buildRefreshTokenRecord(params) {
|
|
@@ -2340,8 +2408,58 @@ var RedisAuthorizationStore = class {
|
|
|
2340
2408
|
}
|
|
2341
2409
|
};
|
|
2342
2410
|
|
|
2343
|
-
// libs/auth/src/session/
|
|
2411
|
+
// libs/auth/src/session/pending-login.ts
|
|
2344
2412
|
var import_utils6 = require("@frontmcp/utils");
|
|
2413
|
+
var SALT = new TextEncoder().encode("frontmcp-pending-login");
|
|
2414
|
+
function keyFor(secret, pendingAuthId) {
|
|
2415
|
+
return (0, import_utils6.hkdfSha256)(secret, SALT, new TextEncoder().encode(`pending-login:${pendingAuthId}`), 32);
|
|
2416
|
+
}
|
|
2417
|
+
function sealPendingLogin(secret, pendingAuthId, state) {
|
|
2418
|
+
const iv = (0, import_utils6.randomBytes)(12);
|
|
2419
|
+
const { ciphertext, tag } = (0, import_utils6.encryptAesGcm)(
|
|
2420
|
+
keyFor(secret, pendingAuthId),
|
|
2421
|
+
new TextEncoder().encode(JSON.stringify(state)),
|
|
2422
|
+
iv
|
|
2423
|
+
);
|
|
2424
|
+
return [iv, tag, ciphertext].map((part) => (0, import_utils6.base64urlEncode)(part)).join(".");
|
|
2425
|
+
}
|
|
2426
|
+
function openPendingLogin(secret, pendingAuthId, sealed) {
|
|
2427
|
+
try {
|
|
2428
|
+
const [iv, tag, ciphertext] = sealed.split(".").map((part) => (0, import_utils6.base64urlDecode)(part));
|
|
2429
|
+
if (!iv || !tag || !ciphertext) return void 0;
|
|
2430
|
+
const plaintext = (0, import_utils6.decryptAesGcm)(keyFor(secret, pendingAuthId), ciphertext, iv, tag);
|
|
2431
|
+
const state = JSON.parse(new TextDecoder().decode(plaintext));
|
|
2432
|
+
return typeof state?.sub === "string" && state.sub.length > 0 ? state : void 0;
|
|
2433
|
+
} catch {
|
|
2434
|
+
return void 0;
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
// libs/auth/src/session/signin-binding.ts
|
|
2439
|
+
var import_utils7 = require("@frontmcp/utils");
|
|
2440
|
+
var SIGNIN_BINDING_COOKIE_PREFIX = "frontmcp_signin_";
|
|
2441
|
+
var SIGNIN_BINDING_SECURE_COOKIE_PREFIX = `__Host-${SIGNIN_BINDING_COOKIE_PREFIX}`;
|
|
2442
|
+
var SIGNIN_BINDING_MAX_AGE_SECONDS = 30 * 60;
|
|
2443
|
+
function signinBindingCookieName(pendingAuthId, options = {}) {
|
|
2444
|
+
const prefix = options.secure ? SIGNIN_BINDING_SECURE_COOKIE_PREFIX : SIGNIN_BINDING_COOKIE_PREFIX;
|
|
2445
|
+
return `${prefix}${(0, import_utils7.sha256Hex)(`signin:${pendingAuthId}`).slice(0, 16)}`;
|
|
2446
|
+
}
|
|
2447
|
+
function createSigninBinding(pendingAuthId, options = {}) {
|
|
2448
|
+
const value = (0, import_utils7.base64urlEncode)((0, import_utils7.randomBytes)(32));
|
|
2449
|
+
return { cookieName: signinBindingCookieName(pendingAuthId, options), value, hash: (0, import_utils7.sha256Hex)(value) };
|
|
2450
|
+
}
|
|
2451
|
+
function signinBindingMatches(cookieHeader, pendingAuthId, expectedHash, options = {}) {
|
|
2452
|
+
if (!expectedHash) return false;
|
|
2453
|
+
const value = (0, import_utils7.getCookie)(cookieHeader, signinBindingCookieName(pendingAuthId, options));
|
|
2454
|
+
if (!value) return false;
|
|
2455
|
+
const encoder = new TextEncoder();
|
|
2456
|
+
const actual = encoder.encode((0, import_utils7.sha256Hex)(value));
|
|
2457
|
+
const expected = encoder.encode(expectedHash);
|
|
2458
|
+
return actual.length === expected.length && (0, import_utils7.timingSafeEqual)(actual, expected);
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
// libs/auth/src/session/storage-authorization.store.ts
|
|
2462
|
+
var import_utils8 = require("@frontmcp/utils");
|
|
2345
2463
|
var StorageAuthorizationStore = class {
|
|
2346
2464
|
codeStore;
|
|
2347
2465
|
pendingStore;
|
|
@@ -2352,9 +2470,9 @@ var StorageAuthorizationStore = class {
|
|
|
2352
2470
|
this.namespace = options.namespace ?? "oauth";
|
|
2353
2471
|
this.storageIsNamespaced = this.isNamespacedStorage(storage);
|
|
2354
2472
|
const base = this.storageIsNamespaced ? storage.namespace(this.namespace) : storage;
|
|
2355
|
-
this.codeStore = new
|
|
2356
|
-
this.pendingStore = new
|
|
2357
|
-
this.refreshStore = new
|
|
2473
|
+
this.codeStore = new import_utils8.TypedStorage(base);
|
|
2474
|
+
this.pendingStore = new import_utils8.TypedStorage(base);
|
|
2475
|
+
this.refreshStore = new import_utils8.TypedStorage(base);
|
|
2358
2476
|
}
|
|
2359
2477
|
// ============================================
|
|
2360
2478
|
// Record builders (pure; shared with in-memory store)
|
|
@@ -2727,11 +2845,11 @@ var authorizationVaultEntrySchema = import_lazy_zod2.z.object({
|
|
|
2727
2845
|
});
|
|
2728
2846
|
|
|
2729
2847
|
// libs/auth/src/session/session-credential-vault.ts
|
|
2730
|
-
var
|
|
2848
|
+
var import_utils10 = require("@frontmcp/utils");
|
|
2731
2849
|
|
|
2732
2850
|
// libs/auth/src/session/vault-encryption.ts
|
|
2733
2851
|
var import_lazy_zod3 = require("@frontmcp/lazy-zod");
|
|
2734
|
-
var
|
|
2852
|
+
var import_utils9 = require("@frontmcp/utils");
|
|
2735
2853
|
var encryptedDataSchema = import_lazy_zod3.z.object({
|
|
2736
2854
|
/** Version for future algorithm changes */
|
|
2737
2855
|
v: import_lazy_zod3.z.literal(1),
|
|
@@ -2771,7 +2889,7 @@ var VaultEncryption = class {
|
|
|
2771
2889
|
];
|
|
2772
2890
|
const ikm = new TextEncoder().encode(ikmParts.join(""));
|
|
2773
2891
|
const infoBytes = new TextEncoder().encode(this.hkdfInfo);
|
|
2774
|
-
const key = await (0,
|
|
2892
|
+
const key = await (0, import_utils9.hkdfSha256)(ikm, new Uint8Array(0), infoBytes, 32);
|
|
2775
2893
|
return key;
|
|
2776
2894
|
}
|
|
2777
2895
|
/**
|
|
@@ -2798,7 +2916,7 @@ var VaultEncryption = class {
|
|
|
2798
2916
|
];
|
|
2799
2917
|
const ikm = new TextEncoder().encode(ikmParts.join(""));
|
|
2800
2918
|
const infoBytes = new TextEncoder().encode(this.hkdfInfo);
|
|
2801
|
-
const key = await (0,
|
|
2919
|
+
const key = await (0, import_utils9.hkdfSha256)(ikm, new Uint8Array(0), infoBytes, 32);
|
|
2802
2920
|
return key;
|
|
2803
2921
|
}
|
|
2804
2922
|
/**
|
|
@@ -2812,14 +2930,14 @@ var VaultEncryption = class {
|
|
|
2812
2930
|
if (key.length !== 32) {
|
|
2813
2931
|
throw new Error("Encryption key must be 32 bytes");
|
|
2814
2932
|
}
|
|
2815
|
-
const iv = (0,
|
|
2816
|
-
const { ciphertext, tag } = await (0,
|
|
2933
|
+
const iv = (0, import_utils9.randomBytes)(12);
|
|
2934
|
+
const { ciphertext, tag } = await (0, import_utils9.encryptAesGcm)(key, new TextEncoder().encode(plaintext), iv);
|
|
2817
2935
|
return {
|
|
2818
2936
|
v: 1,
|
|
2819
2937
|
alg: "aes-256-gcm",
|
|
2820
|
-
iv: (0,
|
|
2821
|
-
ct: (0,
|
|
2822
|
-
tag: (0,
|
|
2938
|
+
iv: (0, import_utils9.base64urlEncode)(iv),
|
|
2939
|
+
ct: (0, import_utils9.base64urlEncode)(ciphertext),
|
|
2940
|
+
tag: (0, import_utils9.base64urlEncode)(tag)
|
|
2823
2941
|
};
|
|
2824
2942
|
}
|
|
2825
2943
|
/**
|
|
@@ -2839,11 +2957,11 @@ var VaultEncryption = class {
|
|
|
2839
2957
|
throw new Error("Invalid encrypted data format");
|
|
2840
2958
|
}
|
|
2841
2959
|
const { iv, ct, tag } = parsed.data;
|
|
2842
|
-
const ivBuffer = (0,
|
|
2843
|
-
const ciphertext = (0,
|
|
2844
|
-
const tagBuffer = (0,
|
|
2960
|
+
const ivBuffer = (0, import_utils9.base64urlDecode)(iv);
|
|
2961
|
+
const ciphertext = (0, import_utils9.base64urlDecode)(ct);
|
|
2962
|
+
const tagBuffer = (0, import_utils9.base64urlDecode)(tag);
|
|
2845
2963
|
try {
|
|
2846
|
-
const plaintext = await (0,
|
|
2964
|
+
const plaintext = await (0, import_utils9.decryptAesGcm)(key, ciphertext, ivBuffer, tagBuffer);
|
|
2847
2965
|
return new TextDecoder().decode(plaintext);
|
|
2848
2966
|
} catch (_error) {
|
|
2849
2967
|
throw new Error("Decryption failed: invalid key or corrupted data");
|
|
@@ -2983,7 +3101,7 @@ var SessionCredentialVault = class {
|
|
|
2983
3101
|
* it expires via TTL when configured.
|
|
2984
3102
|
*/
|
|
2985
3103
|
async rotateVault(sub) {
|
|
2986
|
-
const vaultId = (0,
|
|
3104
|
+
const vaultId = (0, import_utils10.randomUUID)();
|
|
2987
3105
|
await this.storage.set(this.indexKey(sub), vaultId, this.credentialSetOpts);
|
|
2988
3106
|
return vaultId;
|
|
2989
3107
|
}
|
|
@@ -3132,19 +3250,19 @@ var SessionCredentialVault = class {
|
|
|
3132
3250
|
}
|
|
3133
3251
|
};
|
|
3134
3252
|
function resolveVaultPepper(logger) {
|
|
3135
|
-
const fromEnv = (0,
|
|
3253
|
+
const fromEnv = (0, import_utils10.getEnv)("VAULT_SECRET") ?? (0, import_utils10.getEnv)("JWT_SECRET");
|
|
3136
3254
|
if (fromEnv && fromEnv.trim().length > 0) return fromEnv;
|
|
3137
3255
|
logger.warn(
|
|
3138
3256
|
"SessionCredentialVault: neither VAULT_SECRET nor JWT_SECRET is set; using a random per-process pepper. Stored credentials will NOT survive a restart and cannot be shared across instances. Set VAULT_SECRET (or JWT_SECRET) for persistent, multi-instance credential storage."
|
|
3139
3257
|
);
|
|
3140
|
-
return (0,
|
|
3258
|
+
return (0, import_utils10.randomUUID)() + (0, import_utils10.randomUUID)();
|
|
3141
3259
|
}
|
|
3142
3260
|
function errMsg(err) {
|
|
3143
3261
|
return err instanceof Error ? err.message : String(err);
|
|
3144
3262
|
}
|
|
3145
3263
|
|
|
3146
3264
|
// libs/auth/src/session/token-storage.factory.ts
|
|
3147
|
-
var
|
|
3265
|
+
var import_utils11 = require("@frontmcp/utils");
|
|
3148
3266
|
function isRedisTokenStorage(config) {
|
|
3149
3267
|
return typeof config === "object" && config !== null && "redis" in config && !!config.redis;
|
|
3150
3268
|
}
|
|
@@ -3156,7 +3274,7 @@ function isPersistentTokenStorage(config) {
|
|
|
3156
3274
|
}
|
|
3157
3275
|
async function createTokenStorageAdapter(config) {
|
|
3158
3276
|
if (config === void 0 || config === "memory") {
|
|
3159
|
-
const adapter = new
|
|
3277
|
+
const adapter = new import_utils11.MemoryStorageAdapter();
|
|
3160
3278
|
await adapter.connect();
|
|
3161
3279
|
return adapter;
|
|
3162
3280
|
}
|
|
@@ -3173,14 +3291,14 @@ async function createTokenStorageAdapter(config) {
|
|
|
3173
3291
|
}
|
|
3174
3292
|
if (isRedisTokenStorage(config)) {
|
|
3175
3293
|
const { host, port, password, db, tls, keyPrefix } = config.redis;
|
|
3176
|
-
const adapter = new
|
|
3294
|
+
const adapter = new import_utils11.RedisStorageAdapter({
|
|
3177
3295
|
config: { host, port, password, db, tls },
|
|
3178
3296
|
keyPrefix: keyPrefix ?? ""
|
|
3179
3297
|
});
|
|
3180
3298
|
await adapter.connect();
|
|
3181
3299
|
return adapter;
|
|
3182
3300
|
}
|
|
3183
|
-
const fallback = new
|
|
3301
|
+
const fallback = new import_utils11.MemoryStorageAdapter();
|
|
3184
3302
|
await fallback.connect();
|
|
3185
3303
|
return fallback;
|
|
3186
3304
|
}
|
|
@@ -3200,7 +3318,7 @@ async function createSessionCredentialVault(options) {
|
|
|
3200
3318
|
}
|
|
3201
3319
|
|
|
3202
3320
|
// libs/auth/src/session/credential-resume-link.ts
|
|
3203
|
-
var
|
|
3321
|
+
var import_utils12 = require("@frontmcp/utils");
|
|
3204
3322
|
var DEFAULT_RESUME_TTL_MS = 6e5;
|
|
3205
3323
|
function signCredentialResumeToken(input, secret) {
|
|
3206
3324
|
const payload = {
|
|
@@ -3209,7 +3327,7 @@ function signCredentialResumeToken(input, secret) {
|
|
|
3209
3327
|
...input.context !== void 0 ? { context: input.context } : {},
|
|
3210
3328
|
exp: Date.now() + (input.ttlMs ?? DEFAULT_RESUME_TTL_MS)
|
|
3211
3329
|
};
|
|
3212
|
-
const signedJson = (0,
|
|
3330
|
+
const signedJson = (0, import_utils12.signData)(payload, { secret });
|
|
3213
3331
|
return Buffer.from(signedJson, "utf8").toString("base64url");
|
|
3214
3332
|
}
|
|
3215
3333
|
function verifyCredentialResumeToken(token, secret, now = Date.now()) {
|
|
@@ -3219,7 +3337,7 @@ function verifyCredentialResumeToken(token, secret, now = Date.now()) {
|
|
|
3219
3337
|
} catch {
|
|
3220
3338
|
return null;
|
|
3221
3339
|
}
|
|
3222
|
-
const payload = (0,
|
|
3340
|
+
const payload = (0, import_utils12.verifyData)(signedJson, { secret });
|
|
3223
3341
|
if (!payload) return null;
|
|
3224
3342
|
if (typeof payload.sub !== "string" || typeof payload.key !== "string" || !Number.isFinite(payload.exp)) {
|
|
3225
3343
|
return null;
|
|
@@ -3238,7 +3356,7 @@ function buildCredentialResumeUrl(basePath, token) {
|
|
|
3238
3356
|
}
|
|
3239
3357
|
|
|
3240
3358
|
// libs/auth/src/session/incremental-auth-ticket.ts
|
|
3241
|
-
var
|
|
3359
|
+
var import_utils13 = require("@frontmcp/utils");
|
|
3242
3360
|
var DEFAULT_INCREMENTAL_TICKET_TTL_MS = 3e5;
|
|
3243
3361
|
function signIncrementalAuthTicket(input, secret) {
|
|
3244
3362
|
const payload = {
|
|
@@ -3246,10 +3364,10 @@ function signIncrementalAuthTicket(input, secret) {
|
|
|
3246
3364
|
appId: input.appId,
|
|
3247
3365
|
...input.toolId !== void 0 ? { toolId: input.toolId } : {},
|
|
3248
3366
|
...input.priorAppIds !== void 0 ? { priorAppIds: input.priorAppIds } : {},
|
|
3249
|
-
jti: (0,
|
|
3367
|
+
jti: (0, import_utils13.randomUUID)(),
|
|
3250
3368
|
exp: Date.now() + (input.ttlMs ?? DEFAULT_INCREMENTAL_TICKET_TTL_MS)
|
|
3251
3369
|
};
|
|
3252
|
-
const signedJson = (0,
|
|
3370
|
+
const signedJson = (0, import_utils13.signData)(payload, { secret });
|
|
3253
3371
|
return Buffer.from(signedJson, "utf8").toString("base64url");
|
|
3254
3372
|
}
|
|
3255
3373
|
function verifyIncrementalAuthTicket(token, secret, now = Date.now()) {
|
|
@@ -3259,7 +3377,7 @@ function verifyIncrementalAuthTicket(token, secret, now = Date.now()) {
|
|
|
3259
3377
|
} catch {
|
|
3260
3378
|
return null;
|
|
3261
3379
|
}
|
|
3262
|
-
const payload = (0,
|
|
3380
|
+
const payload = (0, import_utils13.verifyData)(signedJson, { secret });
|
|
3263
3381
|
if (!payload) return null;
|
|
3264
3382
|
if (typeof payload.sub !== "string" || payload.sub.length === 0) return null;
|
|
3265
3383
|
if (typeof payload.appId !== "string" || payload.appId.length === 0) return null;
|
|
@@ -3439,7 +3557,7 @@ function errMsg2(err) {
|
|
|
3439
3557
|
var SECURE_STORE_ACCESSOR = /* @__PURE__ */ Symbol.for("frontmcp:SECURE_STORE_ACCESSOR");
|
|
3440
3558
|
|
|
3441
3559
|
// libs/auth/src/session/secure-store-accessor.impl.ts
|
|
3442
|
-
var
|
|
3560
|
+
var import_utils14 = require("@frontmcp/utils");
|
|
3443
3561
|
var GLOBAL_NAMESPACE = "global";
|
|
3444
3562
|
var SecureStoreAccessorImpl = class {
|
|
3445
3563
|
backend;
|
|
@@ -3468,12 +3586,12 @@ var SecureStoreAccessorImpl = class {
|
|
|
3468
3586
|
return GLOBAL_NAMESPACE;
|
|
3469
3587
|
case "session": {
|
|
3470
3588
|
const sid = this.resolveSessionId();
|
|
3471
|
-
return sid ? `s:${(0,
|
|
3589
|
+
return sid ? `s:${(0, import_utils14.sha256Hex)(sid).slice(0, 32)}` : void 0;
|
|
3472
3590
|
}
|
|
3473
3591
|
case "user":
|
|
3474
3592
|
default: {
|
|
3475
3593
|
const sub = this.resolveSub();
|
|
3476
|
-
return sub ? `u:${(0,
|
|
3594
|
+
return sub ? `u:${(0, import_utils14.sha256Hex)(sub).slice(0, 32)}` : void 0;
|
|
3477
3595
|
}
|
|
3478
3596
|
}
|
|
3479
3597
|
}
|
|
@@ -3514,7 +3632,7 @@ function errMsg3(err) {
|
|
|
3514
3632
|
}
|
|
3515
3633
|
|
|
3516
3634
|
// libs/auth/src/session/secure-store.factory.ts
|
|
3517
|
-
var
|
|
3635
|
+
var import_utils15 = require("@frontmcp/utils");
|
|
3518
3636
|
function isCustomBackendConfig(config) {
|
|
3519
3637
|
return typeof config === "object" && config !== null && "backend" in config && !!config.backend;
|
|
3520
3638
|
}
|
|
@@ -3563,7 +3681,7 @@ async function createSecureStore(options) {
|
|
|
3563
3681
|
if (storage) {
|
|
3564
3682
|
adapter = storage;
|
|
3565
3683
|
} else if (kind === "memory") {
|
|
3566
|
-
adapter = new
|
|
3684
|
+
adapter = new import_utils15.MemoryStorageAdapter();
|
|
3567
3685
|
await adapter.connect();
|
|
3568
3686
|
} else {
|
|
3569
3687
|
adapter = await createTokenStorageAdapter(toTokenStorageConfig(config));
|
|
@@ -3577,7 +3695,7 @@ async function createSecureStore(options) {
|
|
|
3577
3695
|
}
|
|
3578
3696
|
|
|
3579
3697
|
// libs/auth/src/session/token.vault.ts
|
|
3580
|
-
var
|
|
3698
|
+
var import_utils16 = require("@frontmcp/utils");
|
|
3581
3699
|
var TokenVault = class {
|
|
3582
3700
|
/** Active key used for new encryptions */
|
|
3583
3701
|
active;
|
|
@@ -3606,14 +3724,14 @@ var TokenVault = class {
|
|
|
3606
3724
|
this.keys.set(k.kid, k.key);
|
|
3607
3725
|
}
|
|
3608
3726
|
async encrypt(plaintext, opts) {
|
|
3609
|
-
const iv = (0,
|
|
3610
|
-
const { ciphertext, tag } = await (0,
|
|
3727
|
+
const iv = (0, import_utils16.randomBytes)(12);
|
|
3728
|
+
const { ciphertext, tag } = await (0, import_utils16.encryptAesGcm)(this.active.key, new TextEncoder().encode(plaintext), iv);
|
|
3611
3729
|
return {
|
|
3612
3730
|
alg: "A256GCM",
|
|
3613
3731
|
kid: this.active.kid,
|
|
3614
|
-
iv: (0,
|
|
3615
|
-
tag: (0,
|
|
3616
|
-
data: (0,
|
|
3732
|
+
iv: (0, import_utils16.base64urlEncode)(iv),
|
|
3733
|
+
tag: (0, import_utils16.base64urlEncode)(tag),
|
|
3734
|
+
data: (0, import_utils16.base64urlEncode)(ciphertext),
|
|
3617
3735
|
exp: opts?.exp,
|
|
3618
3736
|
meta: opts?.meta
|
|
3619
3737
|
};
|
|
@@ -3627,16 +3745,16 @@ var TokenVault = class {
|
|
|
3627
3745
|
}
|
|
3628
3746
|
const key = this.keys.get(blob.kid);
|
|
3629
3747
|
if (!key) throw new Error(`vault_unknown_kid:${blob.kid}`);
|
|
3630
|
-
const iv = (0,
|
|
3631
|
-
const tag = (0,
|
|
3632
|
-
const data = (0,
|
|
3633
|
-
const plaintext = await (0,
|
|
3748
|
+
const iv = (0, import_utils16.base64urlDecode)(blob.iv);
|
|
3749
|
+
const tag = (0, import_utils16.base64urlDecode)(blob.tag);
|
|
3750
|
+
const data = (0, import_utils16.base64urlDecode)(blob.data);
|
|
3751
|
+
const plaintext = await (0, import_utils16.decryptAesGcm)(key, data, iv, tag);
|
|
3634
3752
|
return new TextDecoder().decode(plaintext);
|
|
3635
3753
|
}
|
|
3636
3754
|
};
|
|
3637
3755
|
|
|
3638
3756
|
// libs/auth/src/session/index.ts
|
|
3639
|
-
var
|
|
3757
|
+
var import_utils36 = require("@frontmcp/utils");
|
|
3640
3758
|
|
|
3641
3759
|
// libs/auth/src/session/transport-session.types.ts
|
|
3642
3760
|
var import_lazy_zod4 = require("@frontmcp/lazy-zod");
|
|
@@ -3732,10 +3850,10 @@ var redisConfigSchema = import_lazy_zod4.z.object({
|
|
|
3732
3850
|
});
|
|
3733
3851
|
|
|
3734
3852
|
// libs/auth/src/session/session-crypto.ts
|
|
3735
|
-
var
|
|
3853
|
+
var import_utils18 = require("@frontmcp/utils");
|
|
3736
3854
|
|
|
3737
3855
|
// libs/auth/src/errors/auth-internal.error.ts
|
|
3738
|
-
var
|
|
3856
|
+
var import_utils17 = require("@frontmcp/utils");
|
|
3739
3857
|
var AuthInternalError = class extends Error {
|
|
3740
3858
|
/**
|
|
3741
3859
|
* Unique error ID for tracking in logs.
|
|
@@ -3757,7 +3875,7 @@ var AuthInternalError = class extends Error {
|
|
|
3757
3875
|
super(message);
|
|
3758
3876
|
this.name = this.constructor.name;
|
|
3759
3877
|
this.code = code;
|
|
3760
|
-
this.errorId = `err_${(0,
|
|
3878
|
+
this.errorId = `err_${(0, import_utils17.bytesToHex)((0, import_utils17.randomBytes)(8))}`;
|
|
3761
3879
|
Error.captureStackTrace(this, this.constructor);
|
|
3762
3880
|
}
|
|
3763
3881
|
/**
|
|
@@ -3896,9 +4014,9 @@ var AuthFlowError = class extends AuthInternalError {
|
|
|
3896
4014
|
|
|
3897
4015
|
// libs/auth/src/session/session-crypto.ts
|
|
3898
4016
|
function getSigningSecret(config) {
|
|
3899
|
-
const secret = config?.secret || (0,
|
|
4017
|
+
const secret = config?.secret || (0, import_utils18.getEnv)("MCP_SESSION_SECRET");
|
|
3900
4018
|
if (!secret) {
|
|
3901
|
-
if ((0,
|
|
4019
|
+
if ((0, import_utils18.isProduction)()) {
|
|
3902
4020
|
throw new SessionSecretRequiredError("session signing");
|
|
3903
4021
|
}
|
|
3904
4022
|
console.warn("[SessionCrypto] MCP_SESSION_SECRET not set. Using insecure default for development only.");
|
|
@@ -3910,13 +4028,13 @@ function resolveConfig(config) {
|
|
|
3910
4028
|
return { secret: getSigningSecret(config) };
|
|
3911
4029
|
}
|
|
3912
4030
|
function signSession(session, config) {
|
|
3913
|
-
return (0,
|
|
4031
|
+
return (0, import_utils18.signData)(session, resolveConfig(config));
|
|
3914
4032
|
}
|
|
3915
4033
|
function verifySession(signedData, config) {
|
|
3916
|
-
return (0,
|
|
4034
|
+
return (0, import_utils18.verifyData)(signedData, resolveConfig(config));
|
|
3917
4035
|
}
|
|
3918
4036
|
function verifyOrParseSession(data, config) {
|
|
3919
|
-
return (0,
|
|
4037
|
+
return (0, import_utils18.verifyOrParseData)(data, resolveConfig(config));
|
|
3920
4038
|
}
|
|
3921
4039
|
|
|
3922
4040
|
// libs/auth/src/session/session-rate-limiter.ts
|
|
@@ -4043,7 +4161,7 @@ var SessionRateLimiter = class {
|
|
|
4043
4161
|
var defaultSessionRateLimiter = new SessionRateLimiter();
|
|
4044
4162
|
|
|
4045
4163
|
// libs/auth/src/session/session.transport.ts
|
|
4046
|
-
var
|
|
4164
|
+
var import_utils19 = require("@frontmcp/utils");
|
|
4047
4165
|
var TransportIdGenerator = class {
|
|
4048
4166
|
/**
|
|
4049
4167
|
* Create a transport session ID.
|
|
@@ -4052,7 +4170,7 @@ var TransportIdGenerator = class {
|
|
|
4052
4170
|
* @returns A transport session ID (UUID without dashes)
|
|
4053
4171
|
*/
|
|
4054
4172
|
static createId() {
|
|
4055
|
-
return (0,
|
|
4173
|
+
return (0, import_utils19.randomUUID)().replace(/-/g, "");
|
|
4056
4174
|
}
|
|
4057
4175
|
};
|
|
4058
4176
|
|
|
@@ -4101,7 +4219,7 @@ var TinyTtlCache = class {
|
|
|
4101
4219
|
};
|
|
4102
4220
|
|
|
4103
4221
|
// libs/auth/src/session/utils/auth-token.utils.ts
|
|
4104
|
-
var
|
|
4222
|
+
var import_utils20 = require("@frontmcp/utils");
|
|
4105
4223
|
function isJwt(token) {
|
|
4106
4224
|
if (!token) return false;
|
|
4107
4225
|
return token.split(".").length === 3;
|
|
@@ -4111,7 +4229,7 @@ function getTokenSignatureFingerprint(token) {
|
|
|
4111
4229
|
const sig = token.split(".")[2];
|
|
4112
4230
|
if (sig) return sig;
|
|
4113
4231
|
}
|
|
4114
|
-
return (0,
|
|
4232
|
+
return (0, import_utils20.sha256Base64url)(token);
|
|
4115
4233
|
}
|
|
4116
4234
|
function extractClaimValue(claims, key, validator) {
|
|
4117
4235
|
const value = claims[key];
|
|
@@ -4143,26 +4261,26 @@ function extractBearerToken(header) {
|
|
|
4143
4261
|
}
|
|
4144
4262
|
|
|
4145
4263
|
// libs/auth/src/session/utils/session-crypto.utils.ts
|
|
4146
|
-
var
|
|
4264
|
+
var import_utils21 = require("@frontmcp/utils");
|
|
4147
4265
|
var cachedKey = null;
|
|
4148
4266
|
function getKey() {
|
|
4149
4267
|
if (cachedKey) return cachedKey;
|
|
4150
|
-
const secret = (0,
|
|
4268
|
+
const secret = (0, import_utils21.getEnv)("MCP_SESSION_SECRET");
|
|
4151
4269
|
if (!secret) {
|
|
4152
|
-
if ((0,
|
|
4270
|
+
if ((0, import_utils21.isProduction)()) {
|
|
4153
4271
|
throw new SessionSecretRequiredError("session ID encryption");
|
|
4154
4272
|
}
|
|
4155
4273
|
console.warn(
|
|
4156
4274
|
"[SessionIdUtils] Using machine ID as session encryption secret - NOT SECURE FOR PRODUCTION. Set MCP_SESSION_SECRET environment variable for secure session encryption."
|
|
4157
4275
|
);
|
|
4158
4276
|
}
|
|
4159
|
-
const base = secret || (0,
|
|
4160
|
-
cachedKey = (0,
|
|
4277
|
+
const base = secret || (0, import_utils21.getMachineId)();
|
|
4278
|
+
cachedKey = (0, import_utils21.sha256)(new TextEncoder().encode(base));
|
|
4161
4279
|
return cachedKey;
|
|
4162
4280
|
}
|
|
4163
4281
|
function encryptJson(obj) {
|
|
4164
4282
|
const key = getKey();
|
|
4165
|
-
const encrypted = (0,
|
|
4283
|
+
const encrypted = (0, import_utils21.encryptValue)(obj, key);
|
|
4166
4284
|
return `${encrypted.iv}.${encrypted.tag}.${encrypted.data}`;
|
|
4167
4285
|
}
|
|
4168
4286
|
function decryptSessionJson(sessionId) {
|
|
@@ -4171,7 +4289,7 @@ function decryptSessionJson(sessionId) {
|
|
|
4171
4289
|
const [ivB64, tagB64, ctB64] = parts;
|
|
4172
4290
|
if (!ivB64 || !tagB64 || !ctB64) return null;
|
|
4173
4291
|
const key = getKey();
|
|
4174
|
-
return (0,
|
|
4292
|
+
return (0, import_utils21.decryptValue)({ alg: "A256GCM", iv: ivB64, tag: tagB64, data: ctB64 }, key);
|
|
4175
4293
|
}
|
|
4176
4294
|
function safeDecrypt(sessionId) {
|
|
4177
4295
|
try {
|
|
@@ -4185,11 +4303,11 @@ function resetCachedKey() {
|
|
|
4185
4303
|
}
|
|
4186
4304
|
|
|
4187
4305
|
// libs/auth/src/session/storage/index.ts
|
|
4188
|
-
var
|
|
4189
|
-
var
|
|
4306
|
+
var import_utils25 = require("@frontmcp/utils");
|
|
4307
|
+
var import_utils26 = require("@frontmcp/utils");
|
|
4190
4308
|
|
|
4191
4309
|
// libs/auth/src/session/storage/storage-token-store.ts
|
|
4192
|
-
var
|
|
4310
|
+
var import_utils22 = require("@frontmcp/utils");
|
|
4193
4311
|
var StorageTokenStore = class {
|
|
4194
4312
|
storage;
|
|
4195
4313
|
namespace;
|
|
@@ -4201,13 +4319,13 @@ var StorageTokenStore = class {
|
|
|
4201
4319
|
this.defaultTtlSeconds = options.defaultTtlSeconds;
|
|
4202
4320
|
this.storageIsNamespaced = "namespace" in storage && typeof storage.namespace === "function";
|
|
4203
4321
|
const namespacedStorage = this.storageIsNamespaced ? storage.namespace(this.namespace) : storage;
|
|
4204
|
-
this.storage = new
|
|
4322
|
+
this.storage = new import_utils22.TypedStorage(namespacedStorage);
|
|
4205
4323
|
}
|
|
4206
4324
|
/**
|
|
4207
4325
|
* Allocate a new unique ID for a token record.
|
|
4208
4326
|
*/
|
|
4209
4327
|
allocId() {
|
|
4210
|
-
return (0,
|
|
4328
|
+
return (0, import_utils22.randomUUID)();
|
|
4211
4329
|
}
|
|
4212
4330
|
/**
|
|
4213
4331
|
* Store an encrypted token blob.
|
|
@@ -4270,7 +4388,7 @@ var StorageTokenStore = class {
|
|
|
4270
4388
|
};
|
|
4271
4389
|
|
|
4272
4390
|
// libs/auth/src/session/storage/storage-authorization-vault.ts
|
|
4273
|
-
var
|
|
4391
|
+
var import_utils23 = require("@frontmcp/utils");
|
|
4274
4392
|
var StorageAuthorizationVault = class {
|
|
4275
4393
|
storage;
|
|
4276
4394
|
namespace;
|
|
@@ -4279,7 +4397,7 @@ var StorageAuthorizationVault = class {
|
|
|
4279
4397
|
this.namespace = options.namespace ?? "vault";
|
|
4280
4398
|
this.pendingAuthTtlMs = options.pendingAuthTtlMs ?? 10 * 60 * 1e3;
|
|
4281
4399
|
const namespacedStorage = this.isNamespacedStorage(storage) ? storage.namespace(this.namespace) : storage;
|
|
4282
|
-
this.storage = new
|
|
4400
|
+
this.storage = new import_utils23.TypedStorage(namespacedStorage, {
|
|
4283
4401
|
schema: options.validateOnRead ? authorizationVaultEntrySchema : void 0,
|
|
4284
4402
|
throwOnInvalid: false
|
|
4285
4403
|
});
|
|
@@ -4290,7 +4408,7 @@ var StorageAuthorizationVault = class {
|
|
|
4290
4408
|
async create(params) {
|
|
4291
4409
|
const now = Date.now();
|
|
4292
4410
|
const entry = {
|
|
4293
|
-
id: (0,
|
|
4411
|
+
id: (0, import_utils23.randomUUID)(),
|
|
4294
4412
|
userSub: params.userSub,
|
|
4295
4413
|
userEmail: params.userEmail,
|
|
4296
4414
|
userName: params.userName,
|
|
@@ -4364,7 +4482,7 @@ var StorageAuthorizationVault = class {
|
|
|
4364
4482
|
}
|
|
4365
4483
|
const now = Date.now();
|
|
4366
4484
|
const pendingAuth = {
|
|
4367
|
-
id: (0,
|
|
4485
|
+
id: (0, import_utils23.randomUUID)(),
|
|
4368
4486
|
appId: params.appId,
|
|
4369
4487
|
toolId: params.toolId,
|
|
4370
4488
|
authUrl: params.authUrl,
|
|
@@ -4568,11 +4686,11 @@ var StorageAuthorizationVault = class {
|
|
|
4568
4686
|
};
|
|
4569
4687
|
|
|
4570
4688
|
// libs/auth/src/session/storage/in-memory-authorization-vault.ts
|
|
4571
|
-
var
|
|
4689
|
+
var import_utils24 = require("@frontmcp/utils");
|
|
4572
4690
|
var InMemoryAuthorizationVault = class extends StorageAuthorizationVault {
|
|
4573
4691
|
memoryAdapter;
|
|
4574
4692
|
constructor(options = {}) {
|
|
4575
|
-
const memoryAdapter = new
|
|
4693
|
+
const memoryAdapter = new import_utils24.MemoryStorageAdapter();
|
|
4576
4694
|
super(memoryAdapter, {
|
|
4577
4695
|
namespace: options.namespace ?? "vault",
|
|
4578
4696
|
pendingAuthTtlMs: options.pendingAuthTtlMs
|
|
@@ -4593,7 +4711,7 @@ var InMemoryAuthorizationVault = class extends StorageAuthorizationVault {
|
|
|
4593
4711
|
};
|
|
4594
4712
|
|
|
4595
4713
|
// libs/auth/src/session/redis-session.store.ts
|
|
4596
|
-
var
|
|
4714
|
+
var import_utils27 = require("@frontmcp/utils");
|
|
4597
4715
|
var RedisSessionStore = class {
|
|
4598
4716
|
storage;
|
|
4599
4717
|
keyPrefix;
|
|
@@ -4615,14 +4733,14 @@ var RedisSessionStore = class {
|
|
|
4615
4733
|
});
|
|
4616
4734
|
}
|
|
4617
4735
|
if ("redis" in config && config.redis) {
|
|
4618
|
-
this.storage = new
|
|
4736
|
+
this.storage = new import_utils27.RedisStorageAdapter({
|
|
4619
4737
|
client: config.redis,
|
|
4620
4738
|
keyPrefix: this.keyPrefix
|
|
4621
4739
|
});
|
|
4622
4740
|
this.externalInstance = true;
|
|
4623
4741
|
} else {
|
|
4624
4742
|
const redisConfig = config;
|
|
4625
|
-
this.storage = new
|
|
4743
|
+
this.storage = new import_utils27.RedisStorageAdapter({
|
|
4626
4744
|
config: {
|
|
4627
4745
|
host: redisConfig.host,
|
|
4628
4746
|
port: redisConfig.port ?? 6379,
|
|
@@ -4804,7 +4922,7 @@ var RedisSessionStore = class {
|
|
|
4804
4922
|
* Allocate a new session ID
|
|
4805
4923
|
*/
|
|
4806
4924
|
allocId() {
|
|
4807
|
-
return (0,
|
|
4925
|
+
return (0, import_utils27.randomUUID)();
|
|
4808
4926
|
}
|
|
4809
4927
|
/**
|
|
4810
4928
|
* Disconnect from Redis (only if we created the connection)
|
|
@@ -4840,7 +4958,7 @@ var RedisSessionStore = class {
|
|
|
4840
4958
|
};
|
|
4841
4959
|
|
|
4842
4960
|
// libs/auth/src/session/vercel-kv-session.store.ts
|
|
4843
|
-
var
|
|
4961
|
+
var import_utils28 = require("@frontmcp/utils");
|
|
4844
4962
|
var VercelKvSessionStore = class {
|
|
4845
4963
|
storage;
|
|
4846
4964
|
keyPrefix;
|
|
@@ -4860,7 +4978,7 @@ var VercelKvSessionStore = class {
|
|
|
4860
4978
|
maxRequests: this.security.rateLimiting?.maxRequests
|
|
4861
4979
|
});
|
|
4862
4980
|
}
|
|
4863
|
-
this.storage = new
|
|
4981
|
+
this.storage = new import_utils28.VercelKvStorageAdapter({
|
|
4864
4982
|
url: config.url,
|
|
4865
4983
|
token: config.token,
|
|
4866
4984
|
keyPrefix: this.keyPrefix
|
|
@@ -5034,7 +5152,7 @@ var VercelKvSessionStore = class {
|
|
|
5034
5152
|
* Allocate a new session ID
|
|
5035
5153
|
*/
|
|
5036
5154
|
allocId() {
|
|
5037
|
-
return (0,
|
|
5155
|
+
return (0, import_utils28.randomUUID)();
|
|
5038
5156
|
}
|
|
5039
5157
|
/**
|
|
5040
5158
|
* Disconnect from Vercel KV
|
|
@@ -5063,7 +5181,7 @@ var VercelKvSessionStore = class {
|
|
|
5063
5181
|
};
|
|
5064
5182
|
|
|
5065
5183
|
// libs/auth/src/session/orchestrated-token.store.ts
|
|
5066
|
-
var
|
|
5184
|
+
var import_utils29 = require("@frontmcp/utils");
|
|
5067
5185
|
var InMemoryOrchestratedTokenStore = class {
|
|
5068
5186
|
/** Token storage: Map<compositeKey, ProviderTokenRecord> */
|
|
5069
5187
|
tokens = /* @__PURE__ */ new Map();
|
|
@@ -5105,7 +5223,7 @@ var InMemoryOrchestratedTokenStore = class {
|
|
|
5105
5223
|
}
|
|
5106
5224
|
const info = new TextEncoder().encode(`orchestrated-token:${compositeKey}`);
|
|
5107
5225
|
const salt = new TextEncoder().encode("frontmcp-token-store");
|
|
5108
|
-
const derivedKey = (0,
|
|
5226
|
+
const derivedKey = (0, import_utils29.hkdfSha256)(this.encryptionKey, salt, info, 32);
|
|
5109
5227
|
this.derivedKeys.set(compositeKey, derivedKey);
|
|
5110
5228
|
return derivedKey;
|
|
5111
5229
|
}
|
|
@@ -5115,8 +5233,8 @@ var InMemoryOrchestratedTokenStore = class {
|
|
|
5115
5233
|
async encryptRecord(compositeKey, record) {
|
|
5116
5234
|
const key = await this.deriveKeyForRecord(compositeKey);
|
|
5117
5235
|
const plaintext = JSON.stringify(record);
|
|
5118
|
-
const iv = (0,
|
|
5119
|
-
const { ciphertext, tag } = (0,
|
|
5236
|
+
const iv = (0, import_utils29.randomBytes)(12);
|
|
5237
|
+
const { ciphertext, tag } = (0, import_utils29.encryptAesGcm)(key, new TextEncoder().encode(plaintext), iv);
|
|
5120
5238
|
return JSON.stringify({
|
|
5121
5239
|
iv: Buffer.from(iv).toString("base64url"),
|
|
5122
5240
|
tag: Buffer.from(tag).toString("base64url"),
|
|
@@ -5132,7 +5250,7 @@ var InMemoryOrchestratedTokenStore = class {
|
|
|
5132
5250
|
const ivBytes = Buffer.from(iv, "base64url");
|
|
5133
5251
|
const tagBytes = Buffer.from(tag, "base64url");
|
|
5134
5252
|
const ciphertextBytes = Buffer.from(data, "base64url");
|
|
5135
|
-
const plaintext = (0,
|
|
5253
|
+
const plaintext = (0, import_utils29.decryptAesGcm)(key, ciphertextBytes, ivBytes, tagBytes);
|
|
5136
5254
|
return JSON.parse(new TextDecoder().decode(plaintext));
|
|
5137
5255
|
}
|
|
5138
5256
|
/**
|
|
@@ -5334,7 +5452,7 @@ var InMemoryOrchestratedTokenStore = class {
|
|
|
5334
5452
|
};
|
|
5335
5453
|
|
|
5336
5454
|
// libs/auth/src/session/orchestrated-token.crypto.ts
|
|
5337
|
-
var
|
|
5455
|
+
var import_utils30 = require("@frontmcp/utils");
|
|
5338
5456
|
var HKDF_SALT = new TextEncoder().encode("frontmcp-token-store");
|
|
5339
5457
|
function deriveKeyForRecord(masterKey, compositeKey, cache) {
|
|
5340
5458
|
const cached = cache.get(compositeKey);
|
|
@@ -5342,14 +5460,14 @@ function deriveKeyForRecord(masterKey, compositeKey, cache) {
|
|
|
5342
5460
|
return cached;
|
|
5343
5461
|
}
|
|
5344
5462
|
const info = new TextEncoder().encode(`orchestrated-token:${compositeKey}`);
|
|
5345
|
-
const derived = (0,
|
|
5463
|
+
const derived = (0, import_utils30.hkdfSha256)(masterKey, HKDF_SALT, info, 32);
|
|
5346
5464
|
cache.set(compositeKey, derived);
|
|
5347
5465
|
return derived;
|
|
5348
5466
|
}
|
|
5349
5467
|
function encryptRecord(key, record) {
|
|
5350
5468
|
const plaintext = JSON.stringify(record);
|
|
5351
|
-
const iv = (0,
|
|
5352
|
-
const { ciphertext, tag } = (0,
|
|
5469
|
+
const iv = (0, import_utils30.randomBytes)(12);
|
|
5470
|
+
const { ciphertext, tag } = (0, import_utils30.encryptAesGcm)(key, new TextEncoder().encode(plaintext), iv);
|
|
5353
5471
|
return JSON.stringify({
|
|
5354
5472
|
iv: Buffer.from(iv).toString("base64url"),
|
|
5355
5473
|
tag: Buffer.from(tag).toString("base64url"),
|
|
@@ -5361,7 +5479,7 @@ function decryptRecord(key, encrypted) {
|
|
|
5361
5479
|
const ivBytes = Buffer.from(iv, "base64url");
|
|
5362
5480
|
const tagBytes = Buffer.from(tag, "base64url");
|
|
5363
5481
|
const ciphertextBytes = Buffer.from(data, "base64url");
|
|
5364
|
-
const plaintext = (0,
|
|
5482
|
+
const plaintext = (0, import_utils30.decryptAesGcm)(key, ciphertextBytes, ivBytes, tagBytes);
|
|
5365
5483
|
return JSON.parse(new TextDecoder().decode(plaintext));
|
|
5366
5484
|
}
|
|
5367
5485
|
|
|
@@ -5540,7 +5658,7 @@ var StorageOrchestratedTokenStore = class {
|
|
|
5540
5658
|
};
|
|
5541
5659
|
|
|
5542
5660
|
// libs/auth/src/session/federated-auth.session.ts
|
|
5543
|
-
var
|
|
5661
|
+
var import_utils31 = require("@frontmcp/utils");
|
|
5544
5662
|
function toSessionRecord(session) {
|
|
5545
5663
|
return {
|
|
5546
5664
|
...session,
|
|
@@ -5615,7 +5733,7 @@ var InMemoryFederatedAuthSessionStore = class {
|
|
|
5615
5733
|
createSession(params) {
|
|
5616
5734
|
const now = Date.now();
|
|
5617
5735
|
return {
|
|
5618
|
-
id: (0,
|
|
5736
|
+
id: (0, import_utils31.randomUUID)(),
|
|
5619
5737
|
pendingAuthId: params.pendingAuthId,
|
|
5620
5738
|
clientId: params.clientId,
|
|
5621
5739
|
redirectUri: params.redirectUri,
|
|
@@ -5627,6 +5745,7 @@ var InMemoryFederatedAuthSessionStore = class {
|
|
|
5627
5745
|
providerQueue: [...params.providerIds],
|
|
5628
5746
|
completedProviders: /* @__PURE__ */ new Map(),
|
|
5629
5747
|
skippedProviders: [],
|
|
5748
|
+
signinBinding: params.signinBinding,
|
|
5630
5749
|
createdAt: now,
|
|
5631
5750
|
expiresAt: now + this.sessionTtlMs
|
|
5632
5751
|
};
|
|
@@ -5647,7 +5766,7 @@ var InMemoryFederatedAuthSessionStore = class {
|
|
|
5647
5766
|
function createFederatedAuthSession(params, ttlMs = 15 * 60 * 1e3) {
|
|
5648
5767
|
const now = Date.now();
|
|
5649
5768
|
return {
|
|
5650
|
-
id: (0,
|
|
5769
|
+
id: (0, import_utils31.randomUUID)(),
|
|
5651
5770
|
pendingAuthId: params.pendingAuthId,
|
|
5652
5771
|
clientId: params.clientId,
|
|
5653
5772
|
redirectUri: params.redirectUri,
|
|
@@ -5659,6 +5778,7 @@ function createFederatedAuthSession(params, ttlMs = 15 * 60 * 1e3) {
|
|
|
5659
5778
|
providerQueue: [...params.providerIds],
|
|
5660
5779
|
completedProviders: /* @__PURE__ */ new Map(),
|
|
5661
5780
|
skippedProviders: [],
|
|
5781
|
+
signinBinding: params.signinBinding,
|
|
5662
5782
|
createdAt: now,
|
|
5663
5783
|
expiresAt: now + ttlMs
|
|
5664
5784
|
};
|
|
@@ -5704,7 +5824,7 @@ function startNextProvider(session, pkce, state) {
|
|
|
5704
5824
|
}
|
|
5705
5825
|
|
|
5706
5826
|
// libs/auth/src/session/storage-federated-auth.session.ts
|
|
5707
|
-
var
|
|
5827
|
+
var import_utils32 = require("@frontmcp/utils");
|
|
5708
5828
|
var StorageFederatedAuthSessionStore = class {
|
|
5709
5829
|
storage;
|
|
5710
5830
|
namespace;
|
|
@@ -5713,7 +5833,7 @@ var StorageFederatedAuthSessionStore = class {
|
|
|
5713
5833
|
this.namespace = options.namespace ?? "fed";
|
|
5714
5834
|
this.storageIsNamespaced = this.isNamespacedStorage(storage);
|
|
5715
5835
|
const namespacedStorage = this.storageIsNamespaced ? storage.namespace(this.namespace) : storage;
|
|
5716
|
-
this.storage = new
|
|
5836
|
+
this.storage = new import_utils32.TypedStorage(namespacedStorage);
|
|
5717
5837
|
}
|
|
5718
5838
|
async store(session) {
|
|
5719
5839
|
await this.put(session);
|
|
@@ -5784,7 +5904,7 @@ var InMemoryConsentStore = class {
|
|
|
5784
5904
|
};
|
|
5785
5905
|
|
|
5786
5906
|
// libs/auth/src/session/storage-consent.store.ts
|
|
5787
|
-
var
|
|
5907
|
+
var import_utils33 = require("@frontmcp/utils");
|
|
5788
5908
|
var StorageConsentStore = class {
|
|
5789
5909
|
storage;
|
|
5790
5910
|
namespace;
|
|
@@ -5793,7 +5913,7 @@ var StorageConsentStore = class {
|
|
|
5793
5913
|
this.namespace = options.namespace ?? "remembered-consent";
|
|
5794
5914
|
this.storageIsNamespaced = this.isNamespacedStorage(storage);
|
|
5795
5915
|
const namespacedStorage = this.storageIsNamespaced ? storage.namespace(this.namespace) : storage;
|
|
5796
|
-
this.storage = new
|
|
5916
|
+
this.storage = new import_utils33.TypedStorage(namespacedStorage);
|
|
5797
5917
|
}
|
|
5798
5918
|
async get(userSub, clientId) {
|
|
5799
5919
|
return this.storage.get(this.key(userSub, clientId));
|
|
@@ -5815,7 +5935,7 @@ var StorageConsentStore = class {
|
|
|
5815
5935
|
|
|
5816
5936
|
// libs/auth/src/session/encrypted-authorization-vault.ts
|
|
5817
5937
|
var import_lazy_zod5 = require("@frontmcp/lazy-zod");
|
|
5818
|
-
var
|
|
5938
|
+
var import_utils34 = require("@frontmcp/utils");
|
|
5819
5939
|
var redisVaultEntrySchema = import_lazy_zod5.z.object({
|
|
5820
5940
|
/** Vault ID */
|
|
5821
5941
|
id: import_lazy_zod5.z.string(),
|
|
@@ -5840,7 +5960,7 @@ var redisVaultEntrySchema = import_lazy_zod5.z.object({
|
|
|
5840
5960
|
/** Encrypted sensitive data blob */
|
|
5841
5961
|
encrypted: encryptedDataSchema
|
|
5842
5962
|
});
|
|
5843
|
-
var encryptionContextStorage = new
|
|
5963
|
+
var encryptionContextStorage = new import_utils34.AsyncLocalStorage();
|
|
5844
5964
|
var EncryptedRedisVault = class {
|
|
5845
5965
|
constructor(redis, encryption, namespace = "vault:") {
|
|
5846
5966
|
this.redis = redis;
|
|
@@ -5976,7 +6096,7 @@ var EncryptedRedisVault = class {
|
|
|
5976
6096
|
async create(params) {
|
|
5977
6097
|
const now = Date.now();
|
|
5978
6098
|
const entry = {
|
|
5979
|
-
id: (0,
|
|
6099
|
+
id: (0, import_utils34.randomUUID)(),
|
|
5980
6100
|
userSub: params.userSub,
|
|
5981
6101
|
userEmail: params.userEmail,
|
|
5982
6102
|
userName: params.userName,
|
|
@@ -6035,7 +6155,7 @@ var EncryptedRedisVault = class {
|
|
|
6035
6155
|
}
|
|
6036
6156
|
const now = Date.now();
|
|
6037
6157
|
const pendingAuth = {
|
|
6038
|
-
id: (0,
|
|
6158
|
+
id: (0, import_utils34.randomUUID)(),
|
|
6039
6159
|
appId: params.appId,
|
|
6040
6160
|
toolId: params.toolId,
|
|
6041
6161
|
authUrl: params.authUrl,
|
|
@@ -6213,7 +6333,7 @@ function createEncryptedVault(redis, config = {}) {
|
|
|
6213
6333
|
}
|
|
6214
6334
|
|
|
6215
6335
|
// libs/auth/src/session/token.refresh.ts
|
|
6216
|
-
var
|
|
6336
|
+
var import_utils35 = require("@frontmcp/utils");
|
|
6217
6337
|
function toEpochSeconds(exp) {
|
|
6218
6338
|
if (exp == null) return void 0;
|
|
6219
6339
|
if (exp instanceof Date) return Math.floor(exp.getTime() / 1e3);
|
|
@@ -6235,7 +6355,7 @@ function tryJwtExp(token) {
|
|
|
6235
6355
|
const parts = token.split(".");
|
|
6236
6356
|
if (parts.length < 2) return void 0;
|
|
6237
6357
|
try {
|
|
6238
|
-
const json = JSON.parse(new TextDecoder().decode((0,
|
|
6358
|
+
const json = JSON.parse(new TextDecoder().decode((0, import_utils35.base64urlDecode)(parts[1])));
|
|
6239
6359
|
const e = json?.exp;
|
|
6240
6360
|
return typeof e === "number" ? toEpochSeconds(e) : void 0;
|
|
6241
6361
|
} catch {
|
|
@@ -6298,7 +6418,7 @@ var progressiveAuthStateSchema = import_lazy_zod6.z.object({
|
|
|
6298
6418
|
});
|
|
6299
6419
|
|
|
6300
6420
|
// libs/auth/src/authorization/authorization.class.ts
|
|
6301
|
-
var
|
|
6421
|
+
var import_utils38 = require("@frontmcp/utils");
|
|
6302
6422
|
var AuthorizationBase = class _AuthorizationBase {
|
|
6303
6423
|
id;
|
|
6304
6424
|
isAnonymous;
|
|
@@ -6346,14 +6466,14 @@ var AuthorizationBase = class _AuthorizationBase {
|
|
|
6346
6466
|
* @param fingerprint - Optional client fingerprint for tracking
|
|
6347
6467
|
*/
|
|
6348
6468
|
createTransportSession(protocol, fingerprint) {
|
|
6349
|
-
const sessionId = (0,
|
|
6469
|
+
const sessionId = (0, import_utils38.randomUUID)();
|
|
6350
6470
|
const session = {
|
|
6351
6471
|
id: sessionId,
|
|
6352
6472
|
authorizationId: this.id,
|
|
6353
6473
|
protocol,
|
|
6354
6474
|
createdAt: Date.now(),
|
|
6355
6475
|
expiresAt: this.expiresAt,
|
|
6356
|
-
nodeId: (0,
|
|
6476
|
+
nodeId: (0, import_utils38.getMachineId)(),
|
|
6357
6477
|
clientFingerprint: fingerprint
|
|
6358
6478
|
};
|
|
6359
6479
|
this.#sessions.set(session.id, session);
|
|
@@ -6494,7 +6614,7 @@ var AuthorizationBase = class _AuthorizationBase {
|
|
|
6494
6614
|
*/
|
|
6495
6615
|
static isJwtHeader(segment) {
|
|
6496
6616
|
try {
|
|
6497
|
-
const bytes = (0,
|
|
6617
|
+
const bytes = (0, import_utils38.base64urlDecode)(segment);
|
|
6498
6618
|
const text = new TextDecoder().decode(bytes);
|
|
6499
6619
|
const parsed = JSON.parse(text);
|
|
6500
6620
|
return typeof parsed === "object" && parsed !== null && typeof parsed.alg === "string";
|
|
@@ -6546,7 +6666,7 @@ var AuthorizationBase = class _AuthorizationBase {
|
|
|
6546
6666
|
};
|
|
6547
6667
|
|
|
6548
6668
|
// libs/auth/src/authorization/public.authorization.ts
|
|
6549
|
-
var
|
|
6669
|
+
var import_utils39 = require("@frontmcp/utils");
|
|
6550
6670
|
var PublicAuthorization = class _PublicAuthorization extends AuthorizationBase {
|
|
6551
6671
|
mode = "public";
|
|
6552
6672
|
/**
|
|
@@ -6582,7 +6702,7 @@ var PublicAuthorization = class _PublicAuthorization extends AuthorizationBase {
|
|
|
6582
6702
|
allowedTools = "all",
|
|
6583
6703
|
allowedPrompts = "all"
|
|
6584
6704
|
} = ctx;
|
|
6585
|
-
const uuid = (0,
|
|
6705
|
+
const uuid = (0, import_utils39.randomUUID)();
|
|
6586
6706
|
const sub = `${prefix}:${uuid}`;
|
|
6587
6707
|
const user = {
|
|
6588
6708
|
sub,
|
|
@@ -6666,7 +6786,7 @@ var PublicAuthorization = class _PublicAuthorization extends AuthorizationBase {
|
|
|
6666
6786
|
};
|
|
6667
6787
|
|
|
6668
6788
|
// libs/auth/src/authorization/transparent.authorization.ts
|
|
6669
|
-
var
|
|
6789
|
+
var import_utils40 = require("@frontmcp/utils");
|
|
6670
6790
|
var TransparentAuthorization = class _TransparentAuthorization extends AuthorizationBase {
|
|
6671
6791
|
mode = "transparent";
|
|
6672
6792
|
/**
|
|
@@ -6766,7 +6886,7 @@ var TransparentAuthorization = class _TransparentAuthorization extends Authoriza
|
|
|
6766
6886
|
static generateAuthorizationId(token) {
|
|
6767
6887
|
const parts = token.split(".");
|
|
6768
6888
|
const signature = parts[2] || token;
|
|
6769
|
-
return (0,
|
|
6889
|
+
return (0, import_utils40.sha256Hex)(signature).substring(0, 16);
|
|
6770
6890
|
}
|
|
6771
6891
|
/**
|
|
6772
6892
|
* Get the issuer from the token claims
|
|
@@ -6792,11 +6912,11 @@ var TransparentAuthorization = class _TransparentAuthorization extends Authoriza
|
|
|
6792
6912
|
};
|
|
6793
6913
|
|
|
6794
6914
|
// libs/auth/src/utils/authorization-id.utils.ts
|
|
6795
|
-
var
|
|
6915
|
+
var import_utils41 = require("@frontmcp/utils");
|
|
6796
6916
|
function deriveAuthorizationId(token) {
|
|
6797
6917
|
const parts = token.split(".");
|
|
6798
6918
|
const signature = parts[2] || token;
|
|
6799
|
-
return (0,
|
|
6919
|
+
return (0, import_utils41.sha256Hex)(signature).substring(0, 16);
|
|
6800
6920
|
}
|
|
6801
6921
|
|
|
6802
6922
|
// libs/auth/src/authorization/orchestrated.authorization.ts
|
|
@@ -7165,7 +7285,7 @@ var OrchestratedAuthAccessorAdapter = class {
|
|
|
7165
7285
|
};
|
|
7166
7286
|
|
|
7167
7287
|
// libs/auth/src/authorization/dcr-client.registry.ts
|
|
7168
|
-
var
|
|
7288
|
+
var import_utils42 = require("@frontmcp/utils");
|
|
7169
7289
|
var DEFAULT_MAX_DYNAMIC_CLIENTS = 1e3;
|
|
7170
7290
|
function globMatch(pattern, input) {
|
|
7171
7291
|
let p = 0;
|
|
@@ -7291,7 +7411,7 @@ var DcrClientRegistry = class {
|
|
|
7291
7411
|
if (!isConfidential) return "ok";
|
|
7292
7412
|
if (!client.client_secret) return "invalid";
|
|
7293
7413
|
if (!presentedSecret) return "invalid";
|
|
7294
|
-
return (0,
|
|
7414
|
+
return (0, import_utils42.timingSafeEqual)((0, import_utils42.sha256)(presentedSecret), (0, import_utils42.sha256)(client.client_secret)) ? "ok" : "invalid";
|
|
7295
7415
|
}
|
|
7296
7416
|
/** Whether a client id is known to the registry. */
|
|
7297
7417
|
has(clientId) {
|
|
@@ -7379,7 +7499,7 @@ var DcrClientRegistry = class {
|
|
|
7379
7499
|
if (typeof presented !== "string" || presented.length === 0) {
|
|
7380
7500
|
return false;
|
|
7381
7501
|
}
|
|
7382
|
-
return (0,
|
|
7502
|
+
return (0, import_utils42.timingSafeEqual)((0, import_utils42.sha256)(presented), (0, import_utils42.sha256)(expected));
|
|
7383
7503
|
}
|
|
7384
7504
|
};
|
|
7385
7505
|
|
|
@@ -7708,7 +7828,7 @@ var cimdConfigSchema = import_lazy_zod9.z.object({
|
|
|
7708
7828
|
init_cimd_cache();
|
|
7709
7829
|
|
|
7710
7830
|
// libs/auth/src/cimd/cimd.service.ts
|
|
7711
|
-
var
|
|
7831
|
+
var import_utils43 = require("@frontmcp/utils");
|
|
7712
7832
|
init_cimd_cache();
|
|
7713
7833
|
var CimdService = class {
|
|
7714
7834
|
config;
|
|
@@ -7883,7 +8003,7 @@ var CimdService = class {
|
|
|
7883
8003
|
httpStatus: 304
|
|
7884
8004
|
});
|
|
7885
8005
|
}
|
|
7886
|
-
if ((0,
|
|
8006
|
+
if ((0, import_utils43.isRedirectResponse)(response)) {
|
|
7887
8007
|
const location = response.headers.get("location");
|
|
7888
8008
|
if (!location) {
|
|
7889
8009
|
throw new CimdFetchError(clientId, "Redirect response missing Location header", {
|
|
@@ -8196,7 +8316,16 @@ var upstreamProviderSchema = import_lazy_zod10.z.object({
|
|
|
8196
8316
|
/** User info endpoint (optional, used to enrich the session identity). */
|
|
8197
8317
|
userInfoEndpoint: import_lazy_zod10.z.string().url().optional(),
|
|
8198
8318
|
/** JWKS URI for upstream id_token validation (optional). */
|
|
8199
|
-
jwksUri: import_lazy_zod10.z.string().url().optional()
|
|
8319
|
+
jwksUri: import_lazy_zod10.z.string().url().optional(),
|
|
8320
|
+
/**
|
|
8321
|
+
* The provider's issuer identifier (its OIDC `iss`). When set, an RFC 9207
|
|
8322
|
+
* `iss` on the provider's callback and the `iss` of its `id_token` must name
|
|
8323
|
+
* it (or one of {@link additionalIssuers}). Without it the provider's
|
|
8324
|
+
* `id_token` is not used for identity; `userInfoEndpoint` is asked instead.
|
|
8325
|
+
*/
|
|
8326
|
+
issuer: import_lazy_zod10.z.string().url().optional(),
|
|
8327
|
+
/** Other issuer values this provider legitimately uses. */
|
|
8328
|
+
additionalIssuers: import_lazy_zod10.z.array(import_lazy_zod10.z.string().trim().min(1, "additionalIssuers entries must be non-empty")).optional()
|
|
8200
8329
|
}).refine((p) => !!(p.authorizationEndpoint ?? p.authorizeUrl), {
|
|
8201
8330
|
message: "authorizationEndpoint (or authorizeUrl) is required",
|
|
8202
8331
|
path: ["authorizationEndpoint"]
|
|
@@ -8605,17 +8734,21 @@ var sharedAuthFields = {
|
|
|
8605
8734
|
* Require the OAuth client to be KNOWN (registered via DCR / pre-registered,
|
|
8606
8735
|
* or a CIMD client-id URL) before an authorization request is accepted.
|
|
8607
8736
|
*
|
|
8608
|
-
* @default
|
|
8737
|
+
* @default true
|
|
8609
8738
|
*
|
|
8610
|
-
* SECURITY:
|
|
8611
|
-
*
|
|
8612
|
-
*
|
|
8613
|
-
* (auth-code interception
|
|
8614
|
-
* `
|
|
8615
|
-
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
|
|
8739
|
+
* SECURITY: an unregistered client id has no trusted `redirect_uris` to
|
|
8740
|
+
* validate against, so accepting it lets anyone start a sign-in whose
|
|
8741
|
+
* authorization code is delivered to a redirect_uri of their choosing
|
|
8742
|
+
* (auth-code interception). `false` is for local development only; a
|
|
8743
|
+
* `dcr.allowedRedirectUris` allowlist still constrains such clients.
|
|
8744
|
+
*/
|
|
8745
|
+
requireRegisteredClients: import_lazy_zod14.z.boolean().default(true),
|
|
8746
|
+
/**
|
|
8747
|
+
* Scopes the server may grant (exact values or `*` globs). Requested scopes
|
|
8748
|
+
* outside this list are dropped from the grant. Unset → the standard OpenID
|
|
8749
|
+
* scopes only (see `DEFAULT_ALLOWED_SCOPES`).
|
|
8750
|
+
*/
|
|
8751
|
+
allowedScopes: import_lazy_zod14.z.array(import_lazy_zod14.z.string().trim().min(1, "allowedScopes entries must be non-empty")).optional(),
|
|
8619
8752
|
cimd: cimdConfigSchema.optional(),
|
|
8620
8753
|
// #469 — custom auth UI as a slot→file map + extras name→handler map (per-app
|
|
8621
8754
|
// under splitByApp). Both optional; omitting them serves the built-in pages.
|
|
@@ -9226,6 +9359,50 @@ var AudienceValidator = class _AudienceValidator {
|
|
|
9226
9359
|
}
|
|
9227
9360
|
};
|
|
9228
9361
|
|
|
9362
|
+
// libs/auth/src/utils/scope-grant.utils.ts
|
|
9363
|
+
var DEFAULT_ALLOWED_SCOPES = Object.freeze([
|
|
9364
|
+
"openid",
|
|
9365
|
+
"profile",
|
|
9366
|
+
"email",
|
|
9367
|
+
"offline_access"
|
|
9368
|
+
]);
|
|
9369
|
+
function grantScopes(requested, allowed) {
|
|
9370
|
+
const patterns = allowed ?? DEFAULT_ALLOWED_SCOPES;
|
|
9371
|
+
const granted = [];
|
|
9372
|
+
for (const scope of requested) {
|
|
9373
|
+
if (!scope || granted.includes(scope)) continue;
|
|
9374
|
+
if (patterns.some((pattern) => globMatch(pattern, scope))) granted.push(scope);
|
|
9375
|
+
}
|
|
9376
|
+
return granted;
|
|
9377
|
+
}
|
|
9378
|
+
function advertisedScopes(allowed) {
|
|
9379
|
+
const scopes = [];
|
|
9380
|
+
for (const scope of allowed ?? DEFAULT_ALLOWED_SCOPES) {
|
|
9381
|
+
if (scope && !scope.includes("*") && !scopes.includes(scope)) scopes.push(scope);
|
|
9382
|
+
}
|
|
9383
|
+
return scopes;
|
|
9384
|
+
}
|
|
9385
|
+
|
|
9386
|
+
// libs/auth/src/utils/redirect-uri.utils.ts
|
|
9387
|
+
function isLoopbackRedirectUri(uri) {
|
|
9388
|
+
let url;
|
|
9389
|
+
try {
|
|
9390
|
+
url = new URL(uri);
|
|
9391
|
+
} catch {
|
|
9392
|
+
return false;
|
|
9393
|
+
}
|
|
9394
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
|
|
9395
|
+
if (url.username || url.password) return false;
|
|
9396
|
+
const host = url.hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
9397
|
+
if (host === "localhost" || host === "::1") return true;
|
|
9398
|
+
const m = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(host);
|
|
9399
|
+
if (m) {
|
|
9400
|
+
const octets = m.slice(1).map((n) => Number(n));
|
|
9401
|
+
return octets.every((o) => o >= 0 && o <= 255) && octets[0] === 127;
|
|
9402
|
+
}
|
|
9403
|
+
return false;
|
|
9404
|
+
}
|
|
9405
|
+
|
|
9229
9406
|
// libs/auth/src/vault/auth-providers.types.ts
|
|
9230
9407
|
var import_lazy_zod19 = require("@frontmcp/lazy-zod");
|
|
9231
9408
|
var credentialScopeSchema = import_lazy_zod19.z.enum(["global", "user", "session"]);
|
|
@@ -9468,7 +9645,7 @@ var CredentialCache = class {
|
|
|
9468
9645
|
var AUTH_PROVIDERS_ACCESSOR = /* @__PURE__ */ Symbol.for("frontmcp:AUTH_PROVIDERS_ACCESSOR");
|
|
9469
9646
|
|
|
9470
9647
|
// libs/auth/src/vault/auth-providers.accessor.impl.ts
|
|
9471
|
-
var
|
|
9648
|
+
var import_utils46 = require("@frontmcp/utils");
|
|
9472
9649
|
var AuthProvidersAccessorImpl = class {
|
|
9473
9650
|
constructor(registry, vault, cache, loader, context, logger) {
|
|
9474
9651
|
this.registry = registry;
|
|
@@ -9683,7 +9860,7 @@ var AuthProvidersAccessorImpl = class {
|
|
|
9683
9860
|
return { [credential.headerName]: credential.key };
|
|
9684
9861
|
case "basic": {
|
|
9685
9862
|
const value = `${credential.username}:${credential.password}`;
|
|
9686
|
-
const encoded = credential.encodedValue ?? (0,
|
|
9863
|
+
const encoded = credential.encodedValue ?? (0, import_utils46.base64Encode)(new TextEncoder().encode(value));
|
|
9687
9864
|
return { Authorization: `Basic ${encoded}` };
|
|
9688
9865
|
}
|
|
9689
9866
|
case "custom":
|
|
@@ -10791,6 +10968,211 @@ async function evaluateRebac(policy, ctx) {
|
|
|
10791
10968
|
return { granted: true, evaluatedPolicies: ["relationships"] };
|
|
10792
10969
|
}
|
|
10793
10970
|
|
|
10971
|
+
// libs/auth/src/authorities/authorities.validation.ts
|
|
10972
|
+
var ABAC_OPERATORS = /* @__PURE__ */ new Set([
|
|
10973
|
+
"eq",
|
|
10974
|
+
"neq",
|
|
10975
|
+
"in",
|
|
10976
|
+
"notIn",
|
|
10977
|
+
"gt",
|
|
10978
|
+
"gte",
|
|
10979
|
+
"lt",
|
|
10980
|
+
"lte",
|
|
10981
|
+
"contains",
|
|
10982
|
+
"startsWith",
|
|
10983
|
+
"endsWith",
|
|
10984
|
+
"exists",
|
|
10985
|
+
"matches"
|
|
10986
|
+
]);
|
|
10987
|
+
var CHECK_FIELDS = [
|
|
10988
|
+
"roles",
|
|
10989
|
+
"permissions",
|
|
10990
|
+
"attributes",
|
|
10991
|
+
"relationships",
|
|
10992
|
+
"custom",
|
|
10993
|
+
"guards",
|
|
10994
|
+
"allOf",
|
|
10995
|
+
"anyOf",
|
|
10996
|
+
"not"
|
|
10997
|
+
];
|
|
10998
|
+
var RULE_FIELDS = /* @__PURE__ */ new Set([...CHECK_FIELDS, "operator"]);
|
|
10999
|
+
function isPlainObject(value) {
|
|
11000
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11001
|
+
}
|
|
11002
|
+
function isNonEmptyString(value) {
|
|
11003
|
+
return typeof value === "string" && value.length > 0;
|
|
11004
|
+
}
|
|
11005
|
+
function unknownFields(value, known, path) {
|
|
11006
|
+
const prefix = path ? `${path} has` : "has";
|
|
11007
|
+
return Object.keys(value).filter((key) => !known.has(key)).map((key) => `${prefix} an unknown field "${key}"`);
|
|
11008
|
+
}
|
|
11009
|
+
function checkStringList(value, path) {
|
|
11010
|
+
if (!Array.isArray(value)) return [`${path} must be a list of names`];
|
|
11011
|
+
if (value.length === 0) return [`${path} is empty`];
|
|
11012
|
+
return value.every(isNonEmptyString) ? [] : [`${path} must contain only non-empty names`];
|
|
11013
|
+
}
|
|
11014
|
+
var ALL_OR_ANY = /* @__PURE__ */ new Set(["all", "any"]);
|
|
11015
|
+
function checkAllOrAny(value, path) {
|
|
11016
|
+
if (!isPlainObject(value)) return [`${path} must be an object with "all" or "any"`];
|
|
11017
|
+
const problems = unknownFields(value, ALL_OR_ANY, path);
|
|
11018
|
+
if (value["all"] === void 0 && value["any"] === void 0) {
|
|
11019
|
+
problems.push(`${path} needs "all" or "any"`);
|
|
11020
|
+
}
|
|
11021
|
+
if (value["all"] !== void 0) problems.push(...checkStringList(value["all"], `${path}.all`));
|
|
11022
|
+
if (value["any"] !== void 0) problems.push(...checkStringList(value["any"], `${path}.any`));
|
|
11023
|
+
return problems;
|
|
11024
|
+
}
|
|
11025
|
+
var ATTRIBUTE_FIELDS = /* @__PURE__ */ new Set(["match", "conditions"]);
|
|
11026
|
+
var CONDITION_FIELDS = /* @__PURE__ */ new Set(["path", "op", "value"]);
|
|
11027
|
+
function isValueReference(value) {
|
|
11028
|
+
return isPlainObject(value) && ("fromInput" in value || "fromClaims" in value);
|
|
11029
|
+
}
|
|
11030
|
+
function checkValueReference(value, path) {
|
|
11031
|
+
const ref = value["fromInput"] ?? value["fromClaims"];
|
|
11032
|
+
return Object.keys(value).length === 1 && isNonEmptyString(ref) ? [] : [`${path} must be { fromInput: "<name>" } or { fromClaims: "<path>" }`];
|
|
11033
|
+
}
|
|
11034
|
+
var OPERATOR_VALUES = {
|
|
11035
|
+
in: { accepts: Array.isArray, needs: "a list" },
|
|
11036
|
+
notIn: { accepts: Array.isArray, needs: "a list" },
|
|
11037
|
+
gt: { accepts: (value) => typeof value === "number", needs: "a number" },
|
|
11038
|
+
gte: { accepts: (value) => typeof value === "number", needs: "a number" },
|
|
11039
|
+
lt: { accepts: (value) => typeof value === "number", needs: "a number" },
|
|
11040
|
+
lte: { accepts: (value) => typeof value === "number", needs: "a number" },
|
|
11041
|
+
startsWith: { accepts: (value) => typeof value === "string", needs: "a string" },
|
|
11042
|
+
endsWith: { accepts: (value) => typeof value === "string", needs: "a string" },
|
|
11043
|
+
matches: { accepts: (value) => typeof value === "string", needs: "a string" }
|
|
11044
|
+
};
|
|
11045
|
+
function checkConditionValue(op, condition, path) {
|
|
11046
|
+
const value = condition["value"];
|
|
11047
|
+
if (value === void 0) return [`${path} is missing`];
|
|
11048
|
+
if (op === "exists") {
|
|
11049
|
+
return typeof value === "boolean" ? [] : [`${path} must be true or false for "exists"`];
|
|
11050
|
+
}
|
|
11051
|
+
if (isValueReference(value)) return checkValueReference(value, path);
|
|
11052
|
+
const expected = OPERATOR_VALUES[op];
|
|
11053
|
+
if (expected && !expected.accepts(value)) return [`${path} must be ${expected.needs} for "${op}"`];
|
|
11054
|
+
if (Array.isArray(value) && value.length === 0 && (op === "in" || op === "notIn")) return [`${path} is empty`];
|
|
11055
|
+
return [];
|
|
11056
|
+
}
|
|
11057
|
+
function checkAttributes(value, path) {
|
|
11058
|
+
if (!isPlainObject(value)) return [`${path} must be an object with "match" or "conditions"`];
|
|
11059
|
+
const problems = unknownFields(value, ATTRIBUTE_FIELDS, path);
|
|
11060
|
+
const { match, conditions } = value;
|
|
11061
|
+
if (match === void 0 && conditions === void 0) {
|
|
11062
|
+
problems.push(`${path} needs "match" or "conditions"`);
|
|
11063
|
+
}
|
|
11064
|
+
if (match !== void 0) {
|
|
11065
|
+
if (!isPlainObject(match)) problems.push(`${path}.match must be an object`);
|
|
11066
|
+
else if (Object.keys(match).length === 0) problems.push(`${path}.match is empty`);
|
|
11067
|
+
else {
|
|
11068
|
+
for (const [attribute, expected] of Object.entries(match)) {
|
|
11069
|
+
const at = `${path}.match[${JSON.stringify(attribute)}]`;
|
|
11070
|
+
if (expected === void 0) problems.push(`${at} has no value`);
|
|
11071
|
+
else if (isValueReference(expected)) problems.push(...checkValueReference(expected, at));
|
|
11072
|
+
}
|
|
11073
|
+
}
|
|
11074
|
+
}
|
|
11075
|
+
if (conditions !== void 0) {
|
|
11076
|
+
if (!Array.isArray(conditions)) problems.push(`${path}.conditions must be a list`);
|
|
11077
|
+
else if (conditions.length === 0) problems.push(`${path}.conditions is empty`);
|
|
11078
|
+
else {
|
|
11079
|
+
conditions.forEach((condition, index) => {
|
|
11080
|
+
const at = `${path}.conditions[${index}]`;
|
|
11081
|
+
if (!isPlainObject(condition)) {
|
|
11082
|
+
problems.push(`${at} must be an object with "path" and "op"`);
|
|
11083
|
+
return;
|
|
11084
|
+
}
|
|
11085
|
+
problems.push(...unknownFields(condition, CONDITION_FIELDS, at));
|
|
11086
|
+
if (!isNonEmptyString(condition["path"])) problems.push(`${at}.path must be a non-empty string`);
|
|
11087
|
+
const op = condition["op"];
|
|
11088
|
+
if (!ABAC_OPERATORS.has(op)) {
|
|
11089
|
+
problems.push(`${at}.op "${String(condition["op"])}" is not an operator`);
|
|
11090
|
+
} else {
|
|
11091
|
+
problems.push(...checkConditionValue(op, condition, `${at}.value`));
|
|
11092
|
+
}
|
|
11093
|
+
});
|
|
11094
|
+
}
|
|
11095
|
+
}
|
|
11096
|
+
return problems;
|
|
11097
|
+
}
|
|
11098
|
+
var RELATIONSHIP_FIELDS = /* @__PURE__ */ new Set(["type", "resource", "resourceId"]);
|
|
11099
|
+
function checkResourceId(value, path) {
|
|
11100
|
+
if (isNonEmptyString(value)) return [];
|
|
11101
|
+
if (isPlainObject(value) && Object.keys(value).length === 1) {
|
|
11102
|
+
const ref = value["fromInput"] ?? value["fromClaims"];
|
|
11103
|
+
if (isNonEmptyString(ref)) return [];
|
|
11104
|
+
}
|
|
11105
|
+
return [`${path} must be a string, { fromInput } or { fromClaims }`];
|
|
11106
|
+
}
|
|
11107
|
+
function checkRelationship(value, path) {
|
|
11108
|
+
if (!isPlainObject(value)) return [`${path} must be an object with "type", "resource" and "resourceId"`];
|
|
11109
|
+
const problems = unknownFields(value, RELATIONSHIP_FIELDS, path);
|
|
11110
|
+
if (!isNonEmptyString(value["type"])) problems.push(`${path}.type must be a non-empty string`);
|
|
11111
|
+
if (!isNonEmptyString(value["resource"])) problems.push(`${path}.resource must be a non-empty string`);
|
|
11112
|
+
problems.push(...checkResourceId(value["resourceId"], `${path}.resourceId`));
|
|
11113
|
+
return problems;
|
|
11114
|
+
}
|
|
11115
|
+
function checkRelationships(value, path) {
|
|
11116
|
+
if (!Array.isArray(value)) return checkRelationship(value, path);
|
|
11117
|
+
if (value.length === 0) return [`${path} is empty`];
|
|
11118
|
+
return value.flatMap((relationship, index) => checkRelationship(relationship, `${path}[${index}]`));
|
|
11119
|
+
}
|
|
11120
|
+
function checkRuleList(value, path) {
|
|
11121
|
+
if (!Array.isArray(value)) return [`${path} must be a list of rules`];
|
|
11122
|
+
if (value.length === 0) return [`${path} is empty`];
|
|
11123
|
+
return value.flatMap((rule, index) => checkRule(rule, `${path}[${index}]`));
|
|
11124
|
+
}
|
|
11125
|
+
function checkRule(rule, path) {
|
|
11126
|
+
if (!isPlainObject(rule)) {
|
|
11127
|
+
return [`${path || "the rule"} must be a rule object${typeof rule === "string" ? ", not a profile name" : ""}`];
|
|
11128
|
+
}
|
|
11129
|
+
const problems = unknownFields(rule, RULE_FIELDS, path);
|
|
11130
|
+
if (!CHECK_FIELDS.some((field) => rule[field] !== void 0)) {
|
|
11131
|
+
problems.push(`${path ? `${path} ` : ""}checks nothing`);
|
|
11132
|
+
}
|
|
11133
|
+
if (rule["operator"] !== void 0 && rule["operator"] !== "AND" && rule["operator"] !== "OR") {
|
|
11134
|
+
problems.push(`${path}.operator must be "AND" or "OR"`);
|
|
11135
|
+
}
|
|
11136
|
+
if (rule["roles"] !== void 0) problems.push(...checkAllOrAny(rule["roles"], `${path}.roles`));
|
|
11137
|
+
if (rule["permissions"] !== void 0) problems.push(...checkAllOrAny(rule["permissions"], `${path}.permissions`));
|
|
11138
|
+
if (rule["attributes"] !== void 0) problems.push(...checkAttributes(rule["attributes"], `${path}.attributes`));
|
|
11139
|
+
if (rule["relationships"] !== void 0) {
|
|
11140
|
+
problems.push(...checkRelationships(rule["relationships"], `${path}.relationships`));
|
|
11141
|
+
}
|
|
11142
|
+
if (rule["custom"] !== void 0) {
|
|
11143
|
+
if (!isPlainObject(rule["custom"])) problems.push(`${path}.custom must be an object`);
|
|
11144
|
+
else if (Object.keys(rule["custom"]).length === 0) problems.push(`${path}.custom is empty`);
|
|
11145
|
+
}
|
|
11146
|
+
if (rule["guards"] !== void 0) {
|
|
11147
|
+
const guards = rule["guards"];
|
|
11148
|
+
if (!Array.isArray(guards)) problems.push(`${path}.guards must be a list of functions`);
|
|
11149
|
+
else if (guards.length === 0) problems.push(`${path}.guards is empty`);
|
|
11150
|
+
else if (!guards.every((guard) => typeof guard === "function")) {
|
|
11151
|
+
problems.push(`${path}.guards must contain only functions`);
|
|
11152
|
+
}
|
|
11153
|
+
}
|
|
11154
|
+
if (rule["allOf"] !== void 0) problems.push(...checkRuleList(rule["allOf"], `${path}.allOf`));
|
|
11155
|
+
if (rule["anyOf"] !== void 0) problems.push(...checkRuleList(rule["anyOf"], `${path}.anyOf`));
|
|
11156
|
+
if (rule["not"] !== void 0) problems.push(...checkRule(rule["not"], `${path}.not`));
|
|
11157
|
+
return problems;
|
|
11158
|
+
}
|
|
11159
|
+
function findAuthoritiesRuleProblems(authorities) {
|
|
11160
|
+
if (typeof authorities === "string") {
|
|
11161
|
+
return authorities.length > 0 ? [] : ["the profile name is empty"];
|
|
11162
|
+
}
|
|
11163
|
+
if (Array.isArray(authorities)) {
|
|
11164
|
+
if (authorities.length === 0) return ["the list of profiles is empty"];
|
|
11165
|
+
return authorities.every(isNonEmptyString) ? [] : ["a list of profiles must contain only non-empty profile names"];
|
|
11166
|
+
}
|
|
11167
|
+
if (!isPlainObject(authorities)) {
|
|
11168
|
+
return ["must be a profile name, a list of profile names, or a rule object"];
|
|
11169
|
+
}
|
|
11170
|
+
return checkRule(authorities, "");
|
|
11171
|
+
}
|
|
11172
|
+
function findAuthoritiesProfileProblems(name, policy) {
|
|
11173
|
+
return checkRule(policy, "").map((problem) => `profile "${name}": ${problem.replace(/^\./, "")}`);
|
|
11174
|
+
}
|
|
11175
|
+
|
|
10794
11176
|
// libs/auth/src/authorities/authorities.engine.ts
|
|
10795
11177
|
function mergeResult(base, ...others) {
|
|
10796
11178
|
const evaluatedPolicies = [...base.evaluatedPolicies];
|
|
@@ -10799,8 +11181,12 @@ function mergeResult(base, ...others) {
|
|
|
10799
11181
|
}
|
|
10800
11182
|
return { ...base, evaluatedPolicies };
|
|
10801
11183
|
}
|
|
10802
|
-
function
|
|
10803
|
-
return {
|
|
11184
|
+
function invalidRule(problems, policies = []) {
|
|
11185
|
+
return {
|
|
11186
|
+
granted: false,
|
|
11187
|
+
deniedBy: `invalid authorities rule: ${problems.join("; ")}`,
|
|
11188
|
+
evaluatedPolicies: policies
|
|
11189
|
+
};
|
|
10804
11190
|
}
|
|
10805
11191
|
var AuthoritiesEngine = class {
|
|
10806
11192
|
constructor(profiles, evaluators) {
|
|
@@ -10809,10 +11195,36 @@ var AuthoritiesEngine = class {
|
|
|
10809
11195
|
}
|
|
10810
11196
|
profiles;
|
|
10811
11197
|
evaluators;
|
|
11198
|
+
/** Problems found per rule object, so a rule is validated once however often it is evaluated. */
|
|
11199
|
+
ruleProblems = /* @__PURE__ */ new WeakMap();
|
|
11200
|
+
/**
|
|
11201
|
+
* Problems with an `authorities` value declared on an entry (see {@link findAuthoritiesRuleProblems}),
|
|
11202
|
+
* and each profile name it uses that no registered profile has. The server reports them when it
|
|
11203
|
+
* starts; {@link evaluate} denies such a value (an unknown profile as `profile '…' is not registered`).
|
|
11204
|
+
*/
|
|
11205
|
+
findRuleProblems(authorities) {
|
|
11206
|
+
const problems = findAuthoritiesRuleProblems(authorities);
|
|
11207
|
+
if (problems.length > 0) return problems;
|
|
11208
|
+
const names = typeof authorities === "string" ? [authorities] : Array.isArray(authorities) ? authorities : [];
|
|
11209
|
+
return names.filter((name) => typeof name === "string" && !this.profiles.has(name)).map((name) => `names an unknown profile "${name}"`);
|
|
11210
|
+
}
|
|
11211
|
+
/**
|
|
11212
|
+
* Problems with every registered profile's rule (see {@link findAuthoritiesRuleProblems}).
|
|
11213
|
+
* The server reports them when it starts.
|
|
11214
|
+
*/
|
|
11215
|
+
findProfileProblems() {
|
|
11216
|
+
return Object.entries(this.profiles.getAll()).flatMap(
|
|
11217
|
+
([name, policy]) => findAuthoritiesProfileProblems(name, policy)
|
|
11218
|
+
);
|
|
11219
|
+
}
|
|
10812
11220
|
/**
|
|
10813
11221
|
* Evaluate an AuthoritiesMetadata value (string, string[], or policy object).
|
|
11222
|
+
*
|
|
11223
|
+
* A value that is malformed or checks nothing (see {@link findAuthoritiesRuleProblems}) is denied.
|
|
10814
11224
|
*/
|
|
10815
11225
|
async evaluate(authorities, ctx) {
|
|
11226
|
+
const problems = this.problemsOf(authorities, findAuthoritiesRuleProblems);
|
|
11227
|
+
if (problems.length > 0) return invalidRule(problems);
|
|
10816
11228
|
if (typeof authorities === "string") {
|
|
10817
11229
|
return this.evaluateProfile(authorities, ctx);
|
|
10818
11230
|
}
|
|
@@ -10833,6 +11245,8 @@ var AuthoritiesEngine = class {
|
|
|
10833
11245
|
evaluatedPolicies: [`profile:${name}`]
|
|
10834
11246
|
};
|
|
10835
11247
|
}
|
|
11248
|
+
const problems = this.problemsOf(policy, (rule) => findAuthoritiesProfileProblems(name, rule));
|
|
11249
|
+
if (problems.length > 0) return invalidRule(problems, [`profile:${name}`]);
|
|
10836
11250
|
const result = await this.evaluatePolicy(policy, ctx);
|
|
10837
11251
|
if (!result.granted) {
|
|
10838
11252
|
return {
|
|
@@ -10843,6 +11257,16 @@ var AuthoritiesEngine = class {
|
|
|
10843
11257
|
}
|
|
10844
11258
|
return mergeResult(result, { granted: true, evaluatedPolicies: [`profile:${name}`] });
|
|
10845
11259
|
}
|
|
11260
|
+
/** Validate a rule, reusing the result for a rule object seen before. */
|
|
11261
|
+
problemsOf(rule, find) {
|
|
11262
|
+
if (typeof rule !== "object" || rule === null) return find(rule);
|
|
11263
|
+
let problems = this.ruleProblems.get(rule);
|
|
11264
|
+
if (!problems) {
|
|
11265
|
+
problems = find(rule);
|
|
11266
|
+
this.ruleProblems.set(rule, problems);
|
|
11267
|
+
}
|
|
11268
|
+
return problems;
|
|
11269
|
+
}
|
|
10846
11270
|
/**
|
|
10847
11271
|
* Evaluate an array of profile names (AND semantics).
|
|
10848
11272
|
*/
|
|
@@ -10891,7 +11315,7 @@ var AuthoritiesEngine = class {
|
|
|
10891
11315
|
results.push(await this.evaluateNot(policy.not, ctx));
|
|
10892
11316
|
}
|
|
10893
11317
|
if (results.length === 0) {
|
|
10894
|
-
return
|
|
11318
|
+
return invalidRule(["checks nothing"]);
|
|
10895
11319
|
}
|
|
10896
11320
|
return this.combineResults(results, operator);
|
|
10897
11321
|
}
|
|
@@ -10942,14 +11366,15 @@ var AuthoritiesEngine = class {
|
|
|
10942
11366
|
}
|
|
10943
11367
|
/**
|
|
10944
11368
|
* Evaluate async guard functions in sequence.
|
|
10945
|
-
*
|
|
11369
|
+
* Only `true` grants. A string is the denial message; anything else (`false`, but also
|
|
11370
|
+
* `undefined` from a guard that forgot to return, `null`, `0` or an object) denies.
|
|
10946
11371
|
*/
|
|
10947
11372
|
async evaluateGuards(guards, ctx) {
|
|
10948
11373
|
for (let i = 0; i < guards.length; i++) {
|
|
10949
11374
|
const guard = guards[i];
|
|
10950
11375
|
const result = await guard(ctx);
|
|
10951
|
-
if (result
|
|
10952
|
-
const denialMessage = typeof result === "string" ? result : `guard[${i}] denied`;
|
|
11376
|
+
if (result !== true) {
|
|
11377
|
+
const denialMessage = typeof result === "string" ? result : result === false ? `guard[${i}] denied` : `guard[${i}] did not return true (returned ${result === null ? "null" : typeof result})`;
|
|
10953
11378
|
return {
|
|
10954
11379
|
granted: false,
|
|
10955
11380
|
deniedBy: `guards[${i}]: ${denialMessage}`,
|
|
@@ -11007,6 +11432,13 @@ var AuthoritiesEngine = class {
|
|
|
11007
11432
|
evaluatedPolicies: ["not", ...result.evaluatedPolicies]
|
|
11008
11433
|
};
|
|
11009
11434
|
}
|
|
11435
|
+
/**
|
|
11436
|
+
* The policy a profile name stands for when `evaluate()` is given that name, or `undefined`
|
|
11437
|
+
* when no such profile is registered. Lets callers inspect a named rule without evaluating it.
|
|
11438
|
+
*/
|
|
11439
|
+
resolveProfile(name) {
|
|
11440
|
+
return this.profiles.resolve(name);
|
|
11441
|
+
}
|
|
11010
11442
|
};
|
|
11011
11443
|
|
|
11012
11444
|
// libs/auth/src/authorities/authorities.registry.ts
|
|
@@ -11252,6 +11684,7 @@ var FetchCredentialMiddleware = class {
|
|
|
11252
11684
|
AuthoritiesProfileRegistry,
|
|
11253
11685
|
AuthorityDeniedError,
|
|
11254
11686
|
AuthorizationBase,
|
|
11687
|
+
BUILT_IN_AUTH_PAGE_CSP,
|
|
11255
11688
|
CDN,
|
|
11256
11689
|
CREDENTIALS_ACCESSOR,
|
|
11257
11690
|
CimdClientIdMismatchError,
|
|
@@ -11266,6 +11699,7 @@ var FetchCredentialMiddleware = class {
|
|
|
11266
11699
|
CredentialProviderAlreadyRegisteredError,
|
|
11267
11700
|
CredentialStorageError,
|
|
11268
11701
|
CredentialsAccessorImpl,
|
|
11702
|
+
DEFAULT_ALLOWED_SCOPES,
|
|
11269
11703
|
DEFAULT_INCREMENTAL_TICKET_TTL_MS,
|
|
11270
11704
|
DEFAULT_RESUME_TTL_MS,
|
|
11271
11705
|
DEFAULT_THEME,
|
|
@@ -11304,6 +11738,9 @@ var FetchCredentialMiddleware = class {
|
|
|
11304
11738
|
RedisAuthorizationStore,
|
|
11305
11739
|
RedisSessionStore,
|
|
11306
11740
|
SECURE_STORE_ACCESSOR,
|
|
11741
|
+
SIGNIN_BINDING_COOKIE_PREFIX,
|
|
11742
|
+
SIGNIN_BINDING_MAX_AGE_SECONDS,
|
|
11743
|
+
SIGNIN_BINDING_SECURE_COOKIE_PREFIX,
|
|
11307
11744
|
ScopeDeniedError,
|
|
11308
11745
|
SecureStoreAccessorImpl,
|
|
11309
11746
|
SessionCredentialVault,
|
|
@@ -11331,6 +11768,7 @@ var FetchCredentialMiddleware = class {
|
|
|
11331
11768
|
abacConditionSchema,
|
|
11332
11769
|
abacOperatorSchema,
|
|
11333
11770
|
abacPolicySchema,
|
|
11771
|
+
advertisedScopes,
|
|
11334
11772
|
aiPlatformTypeSchema,
|
|
11335
11773
|
allowsPublicAccess,
|
|
11336
11774
|
apiKeyCredentialSchema,
|
|
@@ -11379,6 +11817,7 @@ var FetchCredentialMiddleware = class {
|
|
|
11379
11817
|
buildToolConsentPage,
|
|
11380
11818
|
buildUnauthorizedHeader,
|
|
11381
11819
|
buildWwwAuthenticate,
|
|
11820
|
+
builtInAuthPageHeaders,
|
|
11382
11821
|
centeredCardLayout,
|
|
11383
11822
|
checkSsrfProtection,
|
|
11384
11823
|
cimdCacheConfigSchema,
|
|
@@ -11398,6 +11837,7 @@ var FetchCredentialMiddleware = class {
|
|
|
11398
11837
|
createLayout,
|
|
11399
11838
|
createSecureStore,
|
|
11400
11839
|
createSessionCredentialVault,
|
|
11840
|
+
createSigninBinding,
|
|
11401
11841
|
createTokenStorageAdapter,
|
|
11402
11842
|
credentialProviderConfigSchema,
|
|
11403
11843
|
credentialSchema,
|
|
@@ -11430,6 +11870,8 @@ var FetchCredentialMiddleware = class {
|
|
|
11430
11870
|
federatedLoginStateSchema,
|
|
11431
11871
|
federatedProviderItemSchema,
|
|
11432
11872
|
federatedSelectionSchema,
|
|
11873
|
+
findAuthoritiesProfileProblems,
|
|
11874
|
+
findAuthoritiesRuleProblems,
|
|
11433
11875
|
flatRemoteProviderFields,
|
|
11434
11876
|
fromSessionRecord,
|
|
11435
11877
|
generateAuthorizationCode,
|
|
@@ -11441,6 +11883,7 @@ var FetchCredentialMiddleware = class {
|
|
|
11441
11883
|
getProviderApps,
|
|
11442
11884
|
getProviderScopes,
|
|
11443
11885
|
getTokenSignatureFingerprint,
|
|
11886
|
+
grantScopes,
|
|
11444
11887
|
hasOnlyLocalhostRedirectUris,
|
|
11445
11888
|
headerApplier,
|
|
11446
11889
|
hkdfSha256,
|
|
@@ -11450,6 +11893,7 @@ var FetchCredentialMiddleware = class {
|
|
|
11450
11893
|
isFrontMcpCredentials,
|
|
11451
11894
|
isJwt,
|
|
11452
11895
|
isLocalMode,
|
|
11896
|
+
isLoopbackRedirectUri,
|
|
11453
11897
|
isOrchestratedLocal,
|
|
11454
11898
|
isOrchestratedMode,
|
|
11455
11899
|
isOrchestratedRemote,
|
|
@@ -11479,6 +11923,7 @@ var FetchCredentialMiddleware = class {
|
|
|
11479
11923
|
noopLogger,
|
|
11480
11924
|
normalizeIssuer,
|
|
11481
11925
|
oauthCredentialSchema,
|
|
11926
|
+
openPendingLogin,
|
|
11482
11927
|
orchestratedLocalSchema,
|
|
11483
11928
|
orchestratedRemoteSchema,
|
|
11484
11929
|
parseAuthOptions,
|
|
@@ -11506,6 +11951,7 @@ var FetchCredentialMiddleware = class {
|
|
|
11506
11951
|
resolveRequiredScopes,
|
|
11507
11952
|
resourceIdRefSchema,
|
|
11508
11953
|
safeDecrypt,
|
|
11954
|
+
sealPendingLogin,
|
|
11509
11955
|
secureStoreConfigSchema,
|
|
11510
11956
|
secureStoreCustomBackendSchema,
|
|
11511
11957
|
secureStoreEncryptionSchema,
|
|
@@ -11516,6 +11962,8 @@ var FetchCredentialMiddleware = class {
|
|
|
11516
11962
|
signCredentialResumeToken,
|
|
11517
11963
|
signIncrementalAuthTicket,
|
|
11518
11964
|
signSession,
|
|
11965
|
+
signinBindingCookieName,
|
|
11966
|
+
signinBindingMatches,
|
|
11519
11967
|
skippedAppBehaviorSchema,
|
|
11520
11968
|
sseTransportStateSchema,
|
|
11521
11969
|
sshKeyCredentialSchema,
|
|
@@ -11548,5 +11996,6 @@ var FetchCredentialMiddleware = class {
|
|
|
11548
11996
|
verifyOrParseSession,
|
|
11549
11997
|
verifyPkce,
|
|
11550
11998
|
verifySession,
|
|
11551
|
-
wideLayout
|
|
11999
|
+
wideLayout,
|
|
12000
|
+
withoutSecretFieldValues
|
|
11552
12001
|
});
|