@frontmcp/auth 1.7.1 → 1.8.0
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/authorization/authorization.class.d.ts +10 -1
- package/authorization/authorization.class.d.ts.map +1 -1
- package/cimd/cimd.validator.d.ts.map +1 -1
- package/detection/auth-provider-detection.d.ts +2 -0
- package/detection/auth-provider-detection.d.ts.map +1 -1
- package/errors/auth-internal.errors.d.ts +12 -0
- package/errors/auth-internal.errors.d.ts.map +1 -1
- package/errors/index.d.ts +1 -1
- package/errors/index.d.ts.map +1 -1
- package/esm/index.mjs +371 -206
- package/esm/package.json +5 -5
- package/index.d.ts +3 -3
- package/index.d.ts.map +1 -1
- package/index.js +452 -280
- package/options/index.d.ts +4 -2
- package/options/index.d.ts.map +1 -1
- package/options/interfaces.d.ts +20 -2
- package/options/interfaces.d.ts.map +1 -1
- package/options/schema.d.ts +13 -1
- package/options/schema.d.ts.map +1 -1
- package/options/static.schema.d.ts +27 -0
- package/options/static.schema.d.ts.map +1 -0
- package/options/typecheck.d.ts.map +1 -1
- package/options/utils.d.ts +7 -2
- package/options/utils.d.ts.map +1 -1
- package/package.json +5 -5
- package/session/authorization.store.d.ts +9 -0
- package/session/authorization.store.d.ts.map +1 -1
- package/session/incremental-auth-ticket.d.ts +69 -0
- package/session/incremental-auth-ticket.d.ts.map +1 -0
- package/session/index.d.ts +2 -0
- package/session/index.d.ts.map +1 -1
- package/ui/templates.d.ts.map +1 -1
package/esm/index.mjs
CHANGED
|
@@ -537,26 +537,78 @@ function checkIpv4(ip) {
|
|
|
537
537
|
}
|
|
538
538
|
return { allowed: true, reason: "" };
|
|
539
539
|
}
|
|
540
|
+
function expandIpv6(ip) {
|
|
541
|
+
let text = ip.toLowerCase();
|
|
542
|
+
if (text.includes("%")) {
|
|
543
|
+
text = text.slice(0, text.indexOf("%"));
|
|
544
|
+
}
|
|
545
|
+
const dottedQuad = text.match(/^(.*:)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/);
|
|
546
|
+
if (dottedQuad) {
|
|
547
|
+
const octets = dottedQuad[2].split(".").map(Number);
|
|
548
|
+
if (octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255)) return null;
|
|
549
|
+
const high = (octets[0] << 8 | octets[1]).toString(16);
|
|
550
|
+
const low = (octets[2] << 8 | octets[3]).toString(16);
|
|
551
|
+
text = `${dottedQuad[1]}${high}:${low}`;
|
|
552
|
+
}
|
|
553
|
+
const halves = text.split("::");
|
|
554
|
+
if (halves.length > 2) return null;
|
|
555
|
+
const parseGroups = (part) => {
|
|
556
|
+
if (part === "") return [];
|
|
557
|
+
const groups = [];
|
|
558
|
+
for (const group of part.split(":")) {
|
|
559
|
+
if (!/^[0-9a-f]{1,4}$/.test(group)) return null;
|
|
560
|
+
groups.push(parseInt(group, 16));
|
|
561
|
+
}
|
|
562
|
+
return groups;
|
|
563
|
+
};
|
|
564
|
+
const head = parseGroups(halves[0]);
|
|
565
|
+
if (head === null) return null;
|
|
566
|
+
if (halves.length === 1) {
|
|
567
|
+
return head.length === 8 ? head : null;
|
|
568
|
+
}
|
|
569
|
+
const tail = parseGroups(halves[1]);
|
|
570
|
+
if (tail === null) return null;
|
|
571
|
+
if (head.length + tail.length > 7) return null;
|
|
572
|
+
return [...head, ...new Array(8 - head.length - tail.length).fill(0), ...tail];
|
|
573
|
+
}
|
|
540
574
|
function checkIpv6(ip) {
|
|
541
|
-
const
|
|
542
|
-
if (
|
|
575
|
+
const groups = expandIpv6(ip);
|
|
576
|
+
if (!groups) {
|
|
577
|
+
return { allowed: false, reason: `Malformed IPv6 address: ${ip}` };
|
|
578
|
+
}
|
|
579
|
+
const isZeroPrefix = groups.slice(0, 7).every((group) => group === 0);
|
|
580
|
+
if (isZeroPrefix && groups[7] === 1) {
|
|
543
581
|
return { allowed: false, reason: "IPv6 loopback address (::1) is not allowed" };
|
|
544
582
|
}
|
|
545
|
-
if (
|
|
583
|
+
if (isZeroPrefix && groups[7] === 0) {
|
|
546
584
|
return { allowed: false, reason: "IPv6 unspecified address (::) is not allowed" };
|
|
547
585
|
}
|
|
548
|
-
if (
|
|
586
|
+
if ((groups[0] & 65472) === 65152) {
|
|
549
587
|
return { allowed: false, reason: "IPv6 link-local addresses (fe80::/10) are not allowed" };
|
|
550
588
|
}
|
|
551
|
-
if (
|
|
589
|
+
if ((groups[0] & 65024) === 64512) {
|
|
552
590
|
return { allowed: false, reason: "IPv6 unique local addresses (fc00::/7) are not allowed" };
|
|
553
591
|
}
|
|
554
|
-
const
|
|
555
|
-
if (
|
|
556
|
-
return checkIpv4(
|
|
592
|
+
const embedded = extractEmbeddedIpv4(groups);
|
|
593
|
+
if (embedded) {
|
|
594
|
+
return checkIpv4(embedded);
|
|
557
595
|
}
|
|
558
596
|
return { allowed: true, reason: "" };
|
|
559
597
|
}
|
|
598
|
+
function extractEmbeddedIpv4(groups) {
|
|
599
|
+
const toDotted = () => {
|
|
600
|
+
const high = groups[6];
|
|
601
|
+
const low = groups[7];
|
|
602
|
+
return `${high >> 8}.${high & 255}.${low >> 8}.${low & 255}`;
|
|
603
|
+
};
|
|
604
|
+
const firstFive = groups.slice(0, 5).every((group) => group === 0);
|
|
605
|
+
if (firstFive && groups[5] === 65535) return toDotted();
|
|
606
|
+
if (firstFive && groups[5] === 0) return toDotted();
|
|
607
|
+
if (groups[0] === 100 && groups[1] === 65435 && groups.slice(2, 6).every((group) => group === 0)) {
|
|
608
|
+
return toDotted();
|
|
609
|
+
}
|
|
610
|
+
return null;
|
|
611
|
+
}
|
|
560
612
|
function isDomainInList(hostname, domainList) {
|
|
561
613
|
const lowerHostname = hostname.toLowerCase();
|
|
562
614
|
for (const domain of domainList) {
|
|
@@ -1326,8 +1378,6 @@ function buildIncrementalAuthPage(params) {
|
|
|
1326
1378
|
|
|
1327
1379
|
<form method="GET" action="${escapeHtml3(callbackPath)}" class="flex gap-3 pt-4 border-t border-gray-100">
|
|
1328
1380
|
<input type="hidden" name="pending_auth_id" value="${escapeHtml3(sessionHint)}">
|
|
1329
|
-
<input type="hidden" name="app_id" value="${escapeHtml3(app.appId)}">
|
|
1330
|
-
<input type="hidden" name="incremental" value="true">
|
|
1331
1381
|
<button type="button" onclick="window.close()"
|
|
1332
1382
|
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">
|
|
1333
1383
|
Cancel
|
|
@@ -1811,6 +1861,7 @@ function buildPendingRecord(params) {
|
|
|
1811
1861
|
createdAt: now,
|
|
1812
1862
|
expiresAt: now + PENDING_AUTH_TTL_MS,
|
|
1813
1863
|
isIncremental: params.isIncremental,
|
|
1864
|
+
incrementalSub: params.incrementalSub,
|
|
1814
1865
|
targetAppId: params.targetAppId,
|
|
1815
1866
|
targetToolId: params.targetToolId,
|
|
1816
1867
|
existingSessionId: params.existingSessionId,
|
|
@@ -2952,6 +3003,44 @@ function buildCredentialResumeUrl(basePath, token) {
|
|
|
2952
3003
|
return `${trimmed}/oauth/connect?token=${encodeURIComponent(token)}`;
|
|
2953
3004
|
}
|
|
2954
3005
|
|
|
3006
|
+
// libs/auth/src/session/incremental-auth-ticket.ts
|
|
3007
|
+
import { randomUUID as randomUUID3, signData as signData2, verifyData as verifyData2 } from "@frontmcp/utils";
|
|
3008
|
+
var DEFAULT_INCREMENTAL_TICKET_TTL_MS = 3e5;
|
|
3009
|
+
function signIncrementalAuthTicket(input, secret) {
|
|
3010
|
+
const payload = {
|
|
3011
|
+
sub: input.sub,
|
|
3012
|
+
appId: input.appId,
|
|
3013
|
+
...input.toolId !== void 0 ? { toolId: input.toolId } : {},
|
|
3014
|
+
...input.priorAppIds !== void 0 ? { priorAppIds: input.priorAppIds } : {},
|
|
3015
|
+
jti: randomUUID3(),
|
|
3016
|
+
exp: Date.now() + (input.ttlMs ?? DEFAULT_INCREMENTAL_TICKET_TTL_MS)
|
|
3017
|
+
};
|
|
3018
|
+
const signedJson = signData2(payload, { secret });
|
|
3019
|
+
return Buffer.from(signedJson, "utf8").toString("base64url");
|
|
3020
|
+
}
|
|
3021
|
+
function verifyIncrementalAuthTicket(token, secret, now = Date.now()) {
|
|
3022
|
+
let signedJson;
|
|
3023
|
+
try {
|
|
3024
|
+
signedJson = Buffer.from(token, "base64url").toString("utf8");
|
|
3025
|
+
} catch {
|
|
3026
|
+
return null;
|
|
3027
|
+
}
|
|
3028
|
+
const payload = verifyData2(signedJson, { secret });
|
|
3029
|
+
if (!payload) return null;
|
|
3030
|
+
if (typeof payload.sub !== "string" || payload.sub.length === 0) return null;
|
|
3031
|
+
if (typeof payload.appId !== "string" || payload.appId.length === 0) return null;
|
|
3032
|
+
if (typeof payload.jti !== "string" || payload.jti.length === 0) return null;
|
|
3033
|
+
if (!Number.isFinite(payload.exp)) return null;
|
|
3034
|
+
if (payload.toolId !== void 0 && typeof payload.toolId !== "string") return null;
|
|
3035
|
+
if (payload.priorAppIds !== void 0 && (!Array.isArray(payload.priorAppIds) || payload.priorAppIds.some((id) => typeof id !== "string"))) {
|
|
3036
|
+
return null;
|
|
3037
|
+
}
|
|
3038
|
+
if (now >= payload.exp) {
|
|
3039
|
+
return null;
|
|
3040
|
+
}
|
|
3041
|
+
return payload;
|
|
3042
|
+
}
|
|
3043
|
+
|
|
2955
3044
|
// libs/auth/src/session/credentials-accessor.ts
|
|
2956
3045
|
var CREDENTIALS_ACCESSOR = /* @__PURE__ */ Symbol.for("frontmcp:CREDENTIALS_ACCESSOR");
|
|
2957
3046
|
|
|
@@ -3416,8 +3505,8 @@ var redisConfigSchema = z4.object({
|
|
|
3416
3505
|
|
|
3417
3506
|
// libs/auth/src/session/session-crypto.ts
|
|
3418
3507
|
import {
|
|
3419
|
-
signData as
|
|
3420
|
-
verifyData as
|
|
3508
|
+
signData as signData3,
|
|
3509
|
+
verifyData as verifyData3,
|
|
3421
3510
|
isSignedData,
|
|
3422
3511
|
verifyOrParseData,
|
|
3423
3512
|
getEnv as getEnv2,
|
|
@@ -3507,6 +3596,22 @@ var SessionSecretRequiredError = class extends AuthInternalError {
|
|
|
3507
3596
|
super(`Session secret is required for ${component}`, "SESSION_SECRET_REQUIRED");
|
|
3508
3597
|
}
|
|
3509
3598
|
};
|
|
3599
|
+
var JwtSecretRequiredError = class extends AuthInternalError {
|
|
3600
|
+
constructor(mode) {
|
|
3601
|
+
super(
|
|
3602
|
+
`JWT_SECRET is required in production for auth.mode "${mode}". Without it the server signs tokens with a random per-process secret, so every restart invalidates outstanding tokens and any second instance or isolate rejects tokens the first one minted.`,
|
|
3603
|
+
"JWT_SECRET_REQUIRED"
|
|
3604
|
+
);
|
|
3605
|
+
}
|
|
3606
|
+
};
|
|
3607
|
+
var JwtSecretWeakError = class extends AuthInternalError {
|
|
3608
|
+
constructor(byteLength) {
|
|
3609
|
+
super(
|
|
3610
|
+
`JWT_SECRET is ${byteLength} bytes; HS256 requires at least 32 (RFC 7518 \xA73.2). A shorter secret is guessable, and whoever guesses it can forge tokens for this server. Generate one with \`openssl rand -hex 32\`.`,
|
|
3611
|
+
"JWT_SECRET_INVALID"
|
|
3612
|
+
);
|
|
3613
|
+
}
|
|
3614
|
+
};
|
|
3510
3615
|
var CredentialProviderAlreadyRegisteredError = class extends AuthInternalError {
|
|
3511
3616
|
constructor(name) {
|
|
3512
3617
|
super(`Credential provider "${name}" is already registered`, "CREDENTIAL_PROVIDER_ALREADY_REGISTERED");
|
|
@@ -3584,10 +3689,10 @@ function resolveConfig(config) {
|
|
|
3584
3689
|
return { secret: getSigningSecret(config) };
|
|
3585
3690
|
}
|
|
3586
3691
|
function signSession(session, config) {
|
|
3587
|
-
return
|
|
3692
|
+
return signData3(session, resolveConfig(config));
|
|
3588
3693
|
}
|
|
3589
3694
|
function verifySession(signedData, config) {
|
|
3590
|
-
return
|
|
3695
|
+
return verifyData3(signedData, resolveConfig(config));
|
|
3591
3696
|
}
|
|
3592
3697
|
function verifyOrParseSession(data, config) {
|
|
3593
3698
|
return verifyOrParseData(data, resolveConfig(config));
|
|
@@ -3717,7 +3822,7 @@ var SessionRateLimiter = class {
|
|
|
3717
3822
|
var defaultSessionRateLimiter = new SessionRateLimiter();
|
|
3718
3823
|
|
|
3719
3824
|
// libs/auth/src/session/session.transport.ts
|
|
3720
|
-
import { randomUUID as
|
|
3825
|
+
import { randomUUID as randomUUID4 } from "@frontmcp/utils";
|
|
3721
3826
|
var TransportIdGenerator = class {
|
|
3722
3827
|
/**
|
|
3723
3828
|
* Create a transport session ID.
|
|
@@ -3726,7 +3831,7 @@ var TransportIdGenerator = class {
|
|
|
3726
3831
|
* @returns A transport session ID (UUID without dashes)
|
|
3727
3832
|
*/
|
|
3728
3833
|
static createId() {
|
|
3729
|
-
return
|
|
3834
|
+
return randomUUID4().replace(/-/g, "");
|
|
3730
3835
|
}
|
|
3731
3836
|
};
|
|
3732
3837
|
|
|
@@ -3863,7 +3968,7 @@ import { TypedStorage as TypedStorage4 } from "@frontmcp/utils";
|
|
|
3863
3968
|
import { EncryptedTypedStorage, EncryptedStorageError } from "@frontmcp/utils";
|
|
3864
3969
|
|
|
3865
3970
|
// libs/auth/src/session/storage/storage-token-store.ts
|
|
3866
|
-
import { randomUUID as
|
|
3971
|
+
import { randomUUID as randomUUID5, TypedStorage as TypedStorage2 } from "@frontmcp/utils";
|
|
3867
3972
|
var StorageTokenStore = class {
|
|
3868
3973
|
storage;
|
|
3869
3974
|
namespace;
|
|
@@ -3881,7 +3986,7 @@ var StorageTokenStore = class {
|
|
|
3881
3986
|
* Allocate a new unique ID for a token record.
|
|
3882
3987
|
*/
|
|
3883
3988
|
allocId() {
|
|
3884
|
-
return
|
|
3989
|
+
return randomUUID5();
|
|
3885
3990
|
}
|
|
3886
3991
|
/**
|
|
3887
3992
|
* Store an encrypted token blob.
|
|
@@ -3944,7 +4049,7 @@ var StorageTokenStore = class {
|
|
|
3944
4049
|
};
|
|
3945
4050
|
|
|
3946
4051
|
// libs/auth/src/session/storage/storage-authorization-vault.ts
|
|
3947
|
-
import { randomUUID as
|
|
4052
|
+
import { randomUUID as randomUUID6, TypedStorage as TypedStorage3 } from "@frontmcp/utils";
|
|
3948
4053
|
var StorageAuthorizationVault = class {
|
|
3949
4054
|
storage;
|
|
3950
4055
|
namespace;
|
|
@@ -3964,7 +4069,7 @@ var StorageAuthorizationVault = class {
|
|
|
3964
4069
|
async create(params) {
|
|
3965
4070
|
const now = Date.now();
|
|
3966
4071
|
const entry = {
|
|
3967
|
-
id:
|
|
4072
|
+
id: randomUUID6(),
|
|
3968
4073
|
userSub: params.userSub,
|
|
3969
4074
|
userEmail: params.userEmail,
|
|
3970
4075
|
userName: params.userName,
|
|
@@ -4038,7 +4143,7 @@ var StorageAuthorizationVault = class {
|
|
|
4038
4143
|
}
|
|
4039
4144
|
const now = Date.now();
|
|
4040
4145
|
const pendingAuth = {
|
|
4041
|
-
id:
|
|
4146
|
+
id: randomUUID6(),
|
|
4042
4147
|
appId: params.appId,
|
|
4043
4148
|
toolId: params.toolId,
|
|
4044
4149
|
authUrl: params.authUrl,
|
|
@@ -4267,7 +4372,7 @@ var InMemoryAuthorizationVault = class extends StorageAuthorizationVault {
|
|
|
4267
4372
|
};
|
|
4268
4373
|
|
|
4269
4374
|
// libs/auth/src/session/redis-session.store.ts
|
|
4270
|
-
import { randomUUID as
|
|
4375
|
+
import { randomUUID as randomUUID7, RedisStorageAdapter as RedisStorageAdapter2 } from "@frontmcp/utils";
|
|
4271
4376
|
var RedisSessionStore = class {
|
|
4272
4377
|
storage;
|
|
4273
4378
|
keyPrefix;
|
|
@@ -4478,7 +4583,7 @@ var RedisSessionStore = class {
|
|
|
4478
4583
|
* Allocate a new session ID
|
|
4479
4584
|
*/
|
|
4480
4585
|
allocId() {
|
|
4481
|
-
return
|
|
4586
|
+
return randomUUID7();
|
|
4482
4587
|
}
|
|
4483
4588
|
/**
|
|
4484
4589
|
* Disconnect from Redis (only if we created the connection)
|
|
@@ -4514,7 +4619,7 @@ var RedisSessionStore = class {
|
|
|
4514
4619
|
};
|
|
4515
4620
|
|
|
4516
4621
|
// libs/auth/src/session/vercel-kv-session.store.ts
|
|
4517
|
-
import { randomUUID as
|
|
4622
|
+
import { randomUUID as randomUUID8, VercelKvStorageAdapter } from "@frontmcp/utils";
|
|
4518
4623
|
var VercelKvSessionStore = class {
|
|
4519
4624
|
storage;
|
|
4520
4625
|
keyPrefix;
|
|
@@ -4708,7 +4813,7 @@ var VercelKvSessionStore = class {
|
|
|
4708
4813
|
* Allocate a new session ID
|
|
4709
4814
|
*/
|
|
4710
4815
|
allocId() {
|
|
4711
|
-
return
|
|
4816
|
+
return randomUUID8();
|
|
4712
4817
|
}
|
|
4713
4818
|
/**
|
|
4714
4819
|
* Disconnect from Vercel KV
|
|
@@ -5214,7 +5319,7 @@ var StorageOrchestratedTokenStore = class {
|
|
|
5214
5319
|
};
|
|
5215
5320
|
|
|
5216
5321
|
// libs/auth/src/session/federated-auth.session.ts
|
|
5217
|
-
import { randomUUID as
|
|
5322
|
+
import { randomUUID as randomUUID9 } from "@frontmcp/utils";
|
|
5218
5323
|
function toSessionRecord(session) {
|
|
5219
5324
|
return {
|
|
5220
5325
|
...session,
|
|
@@ -5289,7 +5394,7 @@ var InMemoryFederatedAuthSessionStore = class {
|
|
|
5289
5394
|
createSession(params) {
|
|
5290
5395
|
const now = Date.now();
|
|
5291
5396
|
return {
|
|
5292
|
-
id:
|
|
5397
|
+
id: randomUUID9(),
|
|
5293
5398
|
pendingAuthId: params.pendingAuthId,
|
|
5294
5399
|
clientId: params.clientId,
|
|
5295
5400
|
redirectUri: params.redirectUri,
|
|
@@ -5321,7 +5426,7 @@ var InMemoryFederatedAuthSessionStore = class {
|
|
|
5321
5426
|
function createFederatedAuthSession(params, ttlMs = 15 * 60 * 1e3) {
|
|
5322
5427
|
const now = Date.now();
|
|
5323
5428
|
return {
|
|
5324
|
-
id:
|
|
5429
|
+
id: randomUUID9(),
|
|
5325
5430
|
pendingAuthId: params.pendingAuthId,
|
|
5326
5431
|
clientId: params.clientId,
|
|
5327
5432
|
redirectUri: params.redirectUri,
|
|
@@ -5489,7 +5594,7 @@ var StorageConsentStore = class {
|
|
|
5489
5594
|
|
|
5490
5595
|
// libs/auth/src/session/encrypted-authorization-vault.ts
|
|
5491
5596
|
import { z as z5 } from "@frontmcp/lazy-zod";
|
|
5492
|
-
import { AsyncLocalStorage, randomUUID as
|
|
5597
|
+
import { AsyncLocalStorage, randomUUID as randomUUID10 } from "@frontmcp/utils";
|
|
5493
5598
|
var redisVaultEntrySchema = z5.object({
|
|
5494
5599
|
/** Vault ID */
|
|
5495
5600
|
id: z5.string(),
|
|
@@ -5650,7 +5755,7 @@ var EncryptedRedisVault = class {
|
|
|
5650
5755
|
async create(params) {
|
|
5651
5756
|
const now = Date.now();
|
|
5652
5757
|
const entry = {
|
|
5653
|
-
id:
|
|
5758
|
+
id: randomUUID10(),
|
|
5654
5759
|
userSub: params.userSub,
|
|
5655
5760
|
userEmail: params.userEmail,
|
|
5656
5761
|
userName: params.userName,
|
|
@@ -5709,7 +5814,7 @@ var EncryptedRedisVault = class {
|
|
|
5709
5814
|
}
|
|
5710
5815
|
const now = Date.now();
|
|
5711
5816
|
const pendingAuth = {
|
|
5712
|
-
id:
|
|
5817
|
+
id: randomUUID10(),
|
|
5713
5818
|
appId: params.appId,
|
|
5714
5819
|
toolId: params.toolId,
|
|
5715
5820
|
authUrl: params.authUrl,
|
|
@@ -5972,7 +6077,7 @@ var progressiveAuthStateSchema = z6.object({
|
|
|
5972
6077
|
});
|
|
5973
6078
|
|
|
5974
6079
|
// libs/auth/src/authorization/authorization.class.ts
|
|
5975
|
-
import { base64urlDecode as base64urlDecode4, getMachineId as getMachineId2, randomUUID as
|
|
6080
|
+
import { base64urlDecode as base64urlDecode4, getMachineId as getMachineId2, randomUUID as randomUUID11 } from "@frontmcp/utils";
|
|
5976
6081
|
var AuthorizationBase = class _AuthorizationBase {
|
|
5977
6082
|
id;
|
|
5978
6083
|
isAnonymous;
|
|
@@ -6020,7 +6125,7 @@ var AuthorizationBase = class _AuthorizationBase {
|
|
|
6020
6125
|
* @param fingerprint - Optional client fingerprint for tracking
|
|
6021
6126
|
*/
|
|
6022
6127
|
createTransportSession(protocol, fingerprint) {
|
|
6023
|
-
const sessionId =
|
|
6128
|
+
const sessionId = randomUUID11();
|
|
6024
6129
|
const session = {
|
|
6025
6130
|
id: sessionId,
|
|
6026
6131
|
authorizationId: this.id,
|
|
@@ -6098,11 +6203,22 @@ var AuthorizationBase = class _AuthorizationBase {
|
|
|
6098
6203
|
/**
|
|
6099
6204
|
* Build URL for progressive/incremental authorization.
|
|
6100
6205
|
* Used when a tool requires authorization for an app that was skipped during initial auth.
|
|
6206
|
+
*
|
|
6207
|
+
* The URL only SKIPS the login step when it carries a valid incremental
|
|
6208
|
+
* ticket (GHSA-2c4g-9c8x-6m8g) — mint one with
|
|
6209
|
+
* {@link signIncrementalAuthTicket} using the server signing secret and pass
|
|
6210
|
+
* it here. Without a ticket the link still works, but the user completes an
|
|
6211
|
+
* ordinary login; `mode=incremental` alone is no longer an authorization
|
|
6212
|
+
* signal and is not emitted.
|
|
6213
|
+
*
|
|
6101
6214
|
* @param appId - App ID that requires authorization
|
|
6102
6215
|
* @param baseUrl - Base URL of the server
|
|
6216
|
+
* @param ticket - Signed incremental-authorization ticket for this subject
|
|
6103
6217
|
*/
|
|
6104
|
-
getProgressiveAuthUrl(appId, baseUrl) {
|
|
6105
|
-
|
|
6218
|
+
getProgressiveAuthUrl(appId, baseUrl, ticket) {
|
|
6219
|
+
const params = new URLSearchParams({ app: appId });
|
|
6220
|
+
if (ticket) params.set("ticket", ticket);
|
|
6221
|
+
return `${baseUrl}/oauth/authorize?${params.toString()}`;
|
|
6106
6222
|
}
|
|
6107
6223
|
/**
|
|
6108
6224
|
* Check if the authorization is expired
|
|
@@ -6209,7 +6325,7 @@ var AuthorizationBase = class _AuthorizationBase {
|
|
|
6209
6325
|
};
|
|
6210
6326
|
|
|
6211
6327
|
// libs/auth/src/authorization/public.authorization.ts
|
|
6212
|
-
import { randomUUID as
|
|
6328
|
+
import { randomUUID as randomUUID12 } from "@frontmcp/utils";
|
|
6213
6329
|
var PublicAuthorization = class _PublicAuthorization extends AuthorizationBase {
|
|
6214
6330
|
mode = "public";
|
|
6215
6331
|
/**
|
|
@@ -6245,7 +6361,7 @@ var PublicAuthorization = class _PublicAuthorization extends AuthorizationBase {
|
|
|
6245
6361
|
allowedTools = "all",
|
|
6246
6362
|
allowedPrompts = "all"
|
|
6247
6363
|
} = ctx;
|
|
6248
|
-
const uuid =
|
|
6364
|
+
const uuid = randomUUID12();
|
|
6249
6365
|
const sub = `${prefix}:${uuid}`;
|
|
6250
6366
|
const user = {
|
|
6251
6367
|
sub,
|
|
@@ -8162,10 +8278,48 @@ var publicAuthOptionsSchema = z11.object({
|
|
|
8162
8278
|
signKey: jwkSchema.or(z11.instanceof(Uint8Array)).optional()
|
|
8163
8279
|
});
|
|
8164
8280
|
|
|
8165
|
-
// libs/auth/src/options/
|
|
8281
|
+
// libs/auth/src/options/static.schema.ts
|
|
8166
8282
|
import { z as z12 } from "@frontmcp/lazy-zod";
|
|
8167
|
-
var
|
|
8168
|
-
mode: z12.literal("
|
|
8283
|
+
var staticAuthOptionsSchema = z12.object({
|
|
8284
|
+
mode: z12.literal("static"),
|
|
8285
|
+
/**
|
|
8286
|
+
* Accepted credentials. Compared against the presented one in constant time,
|
|
8287
|
+
* over SHA-256 digests so neither the value nor its length leaks by timing.
|
|
8288
|
+
*
|
|
8289
|
+
* Read these from the environment — never commit them.
|
|
8290
|
+
*/
|
|
8291
|
+
tokens: z12.array(z12.string().min(1)).min(1),
|
|
8292
|
+
/**
|
|
8293
|
+
* Request header carrying the credential.
|
|
8294
|
+
* @default 'authorization'
|
|
8295
|
+
*/
|
|
8296
|
+
header: z12.string().min(1).default("authorization"),
|
|
8297
|
+
/**
|
|
8298
|
+
* Scheme prefix to strip before comparing, matched case-insensitively. Set to
|
|
8299
|
+
* an empty string for headers that carry a bare token (e.g. `x-api-key`).
|
|
8300
|
+
* @default 'Bearer'
|
|
8301
|
+
*/
|
|
8302
|
+
scheme: z12.string().default("Bearer"),
|
|
8303
|
+
/**
|
|
8304
|
+
* Scopes granted to a request that presents a valid token.
|
|
8305
|
+
* @default ['static']
|
|
8306
|
+
*/
|
|
8307
|
+
scopes: z12.array(z12.string()).default(["static"]),
|
|
8308
|
+
/**
|
|
8309
|
+
* Realm reported in the `WWW-Authenticate` challenge on failure.
|
|
8310
|
+
* @default 'mcp'
|
|
8311
|
+
*/
|
|
8312
|
+
realm: z12.string().default("mcp"),
|
|
8313
|
+
/**
|
|
8314
|
+
* Tool/prompt access configuration, same shape the other modes accept.
|
|
8315
|
+
*/
|
|
8316
|
+
publicAccess: publicAccessConfigSchema.optional()
|
|
8317
|
+
});
|
|
8318
|
+
|
|
8319
|
+
// libs/auth/src/options/transparent.schema.ts
|
|
8320
|
+
import { z as z13 } from "@frontmcp/lazy-zod";
|
|
8321
|
+
var transparentAuthOptionsSchema = z13.object({
|
|
8322
|
+
mode: z13.literal("transparent"),
|
|
8169
8323
|
/**
|
|
8170
8324
|
* Flattened remote provider fields (provider, clientId, clientSecret, scopes, providerConfig)
|
|
8171
8325
|
*/
|
|
@@ -8174,28 +8328,28 @@ var transparentAuthOptionsSchema = z12.object({
|
|
|
8174
8328
|
* Expected token audience
|
|
8175
8329
|
* If not set, defaults to the resource URL
|
|
8176
8330
|
*/
|
|
8177
|
-
expectedAudience:
|
|
8331
|
+
expectedAudience: z13.union([z13.string(), z13.array(z13.string())]).optional(),
|
|
8178
8332
|
/**
|
|
8179
8333
|
* Require an `aud` claim (reject audience-less tokens). Defaults to `false`
|
|
8180
8334
|
* for IdP compatibility; set `true` to reject tokens with no audience.
|
|
8181
8335
|
*/
|
|
8182
|
-
requireAudience:
|
|
8336
|
+
requireAudience: z13.boolean().optional(),
|
|
8183
8337
|
/**
|
|
8184
8338
|
* Required scopes for access
|
|
8185
8339
|
* Empty array means any valid token is accepted
|
|
8186
8340
|
* @default []
|
|
8187
8341
|
*/
|
|
8188
|
-
requiredScopes:
|
|
8342
|
+
requiredScopes: z13.array(z13.string()).default([]),
|
|
8189
8343
|
/**
|
|
8190
8344
|
* Allow anonymous fallback when no token is provided
|
|
8191
8345
|
* @default false
|
|
8192
8346
|
*/
|
|
8193
|
-
allowAnonymous:
|
|
8347
|
+
allowAnonymous: z13.boolean().default(false),
|
|
8194
8348
|
/**
|
|
8195
8349
|
* Scopes granted to anonymous sessions (when allowAnonymous=true)
|
|
8196
8350
|
* @default ['anonymous']
|
|
8197
8351
|
*/
|
|
8198
|
-
anonymousScopes:
|
|
8352
|
+
anonymousScopes: z13.array(z13.string()).default(["anonymous"]),
|
|
8199
8353
|
/**
|
|
8200
8354
|
* Public access config for anonymous users (when allowAnonymous=true)
|
|
8201
8355
|
*/
|
|
@@ -8203,13 +8357,13 @@ var transparentAuthOptionsSchema = z12.object({
|
|
|
8203
8357
|
});
|
|
8204
8358
|
|
|
8205
8359
|
// libs/auth/src/options/orchestrated.schema.ts
|
|
8206
|
-
import { z as
|
|
8207
|
-
var authSlotSchema =
|
|
8208
|
-
var authUiMapSchema =
|
|
8209
|
-
var authExtraHandlerSchema =
|
|
8360
|
+
import { z as z14 } from "@frontmcp/lazy-zod";
|
|
8361
|
+
var authSlotSchema = z14.enum(["login", "consent", "incremental", "federated", "error"]);
|
|
8362
|
+
var authUiMapSchema = z14.partialRecord(authSlotSchema, z14.string().min(1));
|
|
8363
|
+
var authExtraHandlerSchema = z14.custom((v) => typeof v === "function", {
|
|
8210
8364
|
message: "auth.extras entries must be handler functions (input, ctx) => AuthExtraResult."
|
|
8211
8365
|
});
|
|
8212
|
-
var authExtrasMapSchema =
|
|
8366
|
+
var authExtrasMapSchema = z14.record(z14.string().min(1), authExtraHandlerSchema);
|
|
8213
8367
|
var sharedAuthFields = {
|
|
8214
8368
|
local: localSigningConfigSchema.optional(),
|
|
8215
8369
|
tokenStorage: tokenStorageConfigSchema.default("memory"),
|
|
@@ -8217,13 +8371,13 @@ var sharedAuthFields = {
|
|
|
8217
8371
|
// Optional (no default) so an unset value resolves to the in-memory encrypted
|
|
8218
8372
|
// default at runtime; existing configs are unaffected.
|
|
8219
8373
|
secureStore: secureStoreConfigSchema.optional(),
|
|
8220
|
-
allowDefaultPublic:
|
|
8221
|
-
anonymousScopes:
|
|
8374
|
+
allowDefaultPublic: z14.boolean().default(false),
|
|
8375
|
+
anonymousScopes: z14.array(z14.string()).default(["anonymous"]),
|
|
8222
8376
|
publicAccess: publicAccessConfigSchema.optional(),
|
|
8223
8377
|
consent: consentConfigSchema.optional(),
|
|
8224
8378
|
federatedAuth: federatedAuthConfigSchema.optional(),
|
|
8225
8379
|
refresh: tokenRefreshConfigSchema.optional(),
|
|
8226
|
-
expectedAudience:
|
|
8380
|
+
expectedAudience: z14.union([z14.string(), z14.array(z14.string())]).optional(),
|
|
8227
8381
|
incrementalAuth: incrementalAuthConfigSchema.optional(),
|
|
8228
8382
|
/**
|
|
8229
8383
|
* Require the OAuth client to be KNOWN (registered via DCR / pre-registered,
|
|
@@ -8239,46 +8393,46 @@ var sharedAuthFields = {
|
|
|
8239
8393
|
* matching for every client. Clients on a configured
|
|
8240
8394
|
* `dcr.allowedRedirectUris` allowlist still pass.
|
|
8241
8395
|
*/
|
|
8242
|
-
requireRegisteredClients:
|
|
8396
|
+
requireRegisteredClients: z14.boolean().default(false),
|
|
8243
8397
|
cimd: cimdConfigSchema.optional(),
|
|
8244
8398
|
// #469 — custom auth UI as a slot→file map + extras name→handler map (per-app
|
|
8245
8399
|
// under splitByApp). Both optional; omitting them serves the built-in pages.
|
|
8246
8400
|
ui: authUiMapSchema.optional(),
|
|
8247
8401
|
extras: authExtrasMapSchema.optional()
|
|
8248
8402
|
};
|
|
8249
|
-
var loginFieldSchema =
|
|
8250
|
-
type:
|
|
8251
|
-
label:
|
|
8252
|
-
required:
|
|
8253
|
-
placeholder:
|
|
8254
|
-
options:
|
|
8403
|
+
var loginFieldSchema = z14.object({
|
|
8404
|
+
type: z14.enum(["text", "password", "email", "select", "hidden"]),
|
|
8405
|
+
label: z14.string().optional(),
|
|
8406
|
+
required: z14.boolean().optional(),
|
|
8407
|
+
placeholder: z14.string().optional(),
|
|
8408
|
+
options: z14.array(z14.object({ value: z14.string(), label: z14.string() })).optional()
|
|
8255
8409
|
});
|
|
8256
|
-
var loginConfigSchema =
|
|
8257
|
-
title:
|
|
8258
|
-
subtitle:
|
|
8259
|
-
logoUri:
|
|
8260
|
-
fields:
|
|
8410
|
+
var loginConfigSchema = z14.object({
|
|
8411
|
+
title: z14.string().optional(),
|
|
8412
|
+
subtitle: z14.string().optional(),
|
|
8413
|
+
logoUri: z14.string().optional(),
|
|
8414
|
+
fields: z14.record(z14.string(), loginFieldSchema).optional(),
|
|
8261
8415
|
// Full HTML override — a function, validated structurally like other callbacks
|
|
8262
8416
|
// in the codebase (see http/cors handlers using z.custom<…>).
|
|
8263
|
-
render:
|
|
8417
|
+
render: z14.custom((v) => typeof v === "function", {
|
|
8264
8418
|
message: "login.render must be a function"
|
|
8265
8419
|
}).optional(),
|
|
8266
|
-
subject:
|
|
8267
|
-
fromField:
|
|
8268
|
-
strategy:
|
|
8420
|
+
subject: z14.object({
|
|
8421
|
+
fromField: z14.string().optional(),
|
|
8422
|
+
strategy: z14.enum(["per-session", "per-account"]).optional()
|
|
8269
8423
|
}).optional()
|
|
8270
8424
|
});
|
|
8271
|
-
var authenticateFnSchema =
|
|
8425
|
+
var authenticateFnSchema = z14.custom((v) => typeof v === "function", {
|
|
8272
8426
|
message: "authenticate must be a function"
|
|
8273
8427
|
});
|
|
8274
|
-
var localAuthSchema =
|
|
8275
|
-
mode:
|
|
8428
|
+
var localAuthSchema = z14.object({
|
|
8429
|
+
mode: z14.literal("local"),
|
|
8276
8430
|
...sharedAuthFields,
|
|
8277
8431
|
// #468 — opt-out of the email requirement at /oauth/callback for
|
|
8278
8432
|
// single-operator local setups. Defaults preserve the historical behavior
|
|
8279
8433
|
// (email required) so existing configs are unaffected.
|
|
8280
|
-
requireEmail:
|
|
8281
|
-
anonymousSubject:
|
|
8434
|
+
requireEmail: z14.boolean().default(true),
|
|
8435
|
+
anonymousSubject: z14.string().min(1).default("local-operator"),
|
|
8282
8436
|
// Checkpoint 3a — declarative login customization + custom verification.
|
|
8283
8437
|
// Both optional; omitting them preserves the default login path exactly.
|
|
8284
8438
|
login: loginConfigSchema.optional(),
|
|
@@ -8286,7 +8440,7 @@ var localAuthSchema = z13.object({
|
|
|
8286
8440
|
// Multi-OAuth-provider orchestration — declare upstream providers (GitHub,
|
|
8287
8441
|
// Slack, Jira, …) to federate at /oauth/authorize. Optional; omitting it
|
|
8288
8442
|
// preserves the default single-operator local login exactly.
|
|
8289
|
-
providers:
|
|
8443
|
+
providers: z14.array(upstreamProviderSchema).optional(),
|
|
8290
8444
|
// Local-AS Dynamic Client Registration control surface (#462) — gate
|
|
8291
8445
|
// `POST /oauth/register`, allowlist redirect_uris/client_ids, require an
|
|
8292
8446
|
// initial access token, and seed pre-registered trusted clients. Optional;
|
|
@@ -8294,8 +8448,8 @@ var localAuthSchema = z13.object({
|
|
|
8294
8448
|
// no allowlist; no initial access token).
|
|
8295
8449
|
dcr: localDcrConfigSchema.optional()
|
|
8296
8450
|
});
|
|
8297
|
-
var remoteAuthSchema =
|
|
8298
|
-
mode:
|
|
8451
|
+
var remoteAuthSchema = z14.object({
|
|
8452
|
+
mode: z14.literal("remote"),
|
|
8299
8453
|
...flatRemoteProviderFields,
|
|
8300
8454
|
...sharedAuthFields
|
|
8301
8455
|
});
|
|
@@ -8303,21 +8457,22 @@ var orchestratedLocalSchema = localAuthSchema;
|
|
|
8303
8457
|
var orchestratedRemoteSchema = remoteAuthSchema;
|
|
8304
8458
|
|
|
8305
8459
|
// libs/auth/src/options/schema.ts
|
|
8306
|
-
import { z as
|
|
8307
|
-
var authOptionsSchema =
|
|
8460
|
+
import { z as z15 } from "@frontmcp/lazy-zod";
|
|
8461
|
+
var authOptionsSchema = z15.union([
|
|
8308
8462
|
publicAuthOptionsSchema,
|
|
8463
|
+
staticAuthOptionsSchema,
|
|
8309
8464
|
transparentAuthOptionsSchema,
|
|
8310
8465
|
localAuthSchema,
|
|
8311
8466
|
remoteAuthSchema
|
|
8312
8467
|
]);
|
|
8313
8468
|
|
|
8314
8469
|
// libs/auth/src/options/app-auth.schema.ts
|
|
8315
|
-
import { z as
|
|
8470
|
+
import { z as z16 } from "@frontmcp/lazy-zod";
|
|
8316
8471
|
var standaloneOptionSchema = {
|
|
8317
|
-
standalone:
|
|
8318
|
-
excludeFromParent:
|
|
8472
|
+
standalone: z16.boolean().optional(),
|
|
8473
|
+
excludeFromParent: z16.boolean().optional()
|
|
8319
8474
|
};
|
|
8320
|
-
var appAuthOptionsSchema =
|
|
8475
|
+
var appAuthOptionsSchema = z16.union([
|
|
8321
8476
|
publicAuthOptionsSchema.extend(standaloneOptionSchema),
|
|
8322
8477
|
transparentAuthOptionsSchema.extend(standaloneOptionSchema),
|
|
8323
8478
|
localAuthSchema.extend(standaloneOptionSchema),
|
|
@@ -8331,6 +8486,9 @@ function parseAuthOptions(input) {
|
|
|
8331
8486
|
function isPublicMode(options) {
|
|
8332
8487
|
return options.mode === "public";
|
|
8333
8488
|
}
|
|
8489
|
+
function isStaticMode(options) {
|
|
8490
|
+
return options.mode === "static";
|
|
8491
|
+
}
|
|
8334
8492
|
function isTransparentMode(options) {
|
|
8335
8493
|
return options.mode === "transparent";
|
|
8336
8494
|
}
|
|
@@ -8357,108 +8515,108 @@ function allowsPublicAccess(options) {
|
|
|
8357
8515
|
}
|
|
8358
8516
|
|
|
8359
8517
|
// libs/auth/src/consent/consent.types.ts
|
|
8360
|
-
import { z as
|
|
8361
|
-
var consentToolItemSchema =
|
|
8518
|
+
import { z as z17 } from "@frontmcp/lazy-zod";
|
|
8519
|
+
var consentToolItemSchema = z17.object({
|
|
8362
8520
|
/** Tool ID (e.g., 'slack:send_message') */
|
|
8363
|
-
id:
|
|
8521
|
+
id: z17.string().min(1),
|
|
8364
8522
|
/** Tool name for display */
|
|
8365
|
-
name:
|
|
8523
|
+
name: z17.string().min(1),
|
|
8366
8524
|
/** Tool description */
|
|
8367
|
-
description:
|
|
8525
|
+
description: z17.string().optional(),
|
|
8368
8526
|
/** App ID this tool belongs to */
|
|
8369
|
-
appId:
|
|
8527
|
+
appId: z17.string().min(1),
|
|
8370
8528
|
/** App name for display */
|
|
8371
|
-
appName:
|
|
8529
|
+
appName: z17.string().min(1),
|
|
8372
8530
|
/** Whether the tool is selected by default */
|
|
8373
|
-
defaultSelected:
|
|
8531
|
+
defaultSelected: z17.boolean().default(true),
|
|
8374
8532
|
/** Whether this tool requires specific scopes */
|
|
8375
|
-
requiredScopes:
|
|
8533
|
+
requiredScopes: z17.array(z17.string()).optional(),
|
|
8376
8534
|
/** Category for grouping (e.g., 'read', 'write', 'admin') */
|
|
8377
|
-
category:
|
|
8535
|
+
category: z17.string().optional()
|
|
8378
8536
|
});
|
|
8379
|
-
var consentSelectionSchema =
|
|
8537
|
+
var consentSelectionSchema = z17.object({
|
|
8380
8538
|
/** Selected tool IDs */
|
|
8381
|
-
selectedTools:
|
|
8539
|
+
selectedTools: z17.array(z17.string()),
|
|
8382
8540
|
/** Whether all tools were selected */
|
|
8383
|
-
allSelected:
|
|
8541
|
+
allSelected: z17.boolean(),
|
|
8384
8542
|
/** Timestamp when consent was given */
|
|
8385
|
-
consentedAt:
|
|
8543
|
+
consentedAt: z17.string().datetime(),
|
|
8386
8544
|
/** Consent version for tracking changes */
|
|
8387
|
-
consentVersion:
|
|
8545
|
+
consentVersion: z17.string().default("1.0")
|
|
8388
8546
|
});
|
|
8389
|
-
var consentStateSchema =
|
|
8547
|
+
var consentStateSchema = z17.object({
|
|
8390
8548
|
/** Whether consent flow is enabled */
|
|
8391
|
-
enabled:
|
|
8549
|
+
enabled: z17.boolean(),
|
|
8392
8550
|
/** Available tools for consent */
|
|
8393
|
-
availableTools:
|
|
8551
|
+
availableTools: z17.array(consentToolItemSchema),
|
|
8394
8552
|
/** Pre-selected tools (from previous consent or defaults) */
|
|
8395
|
-
preselectedTools:
|
|
8553
|
+
preselectedTools: z17.array(z17.string()).optional(),
|
|
8396
8554
|
/** Whether to show all tools or group by app */
|
|
8397
|
-
groupByApp:
|
|
8555
|
+
groupByApp: z17.boolean().default(true),
|
|
8398
8556
|
/** Custom consent message */
|
|
8399
|
-
customMessage:
|
|
8557
|
+
customMessage: z17.string().optional()
|
|
8400
8558
|
});
|
|
8401
|
-
var federatedProviderItemSchema =
|
|
8559
|
+
var federatedProviderItemSchema = z17.object({
|
|
8402
8560
|
/** Provider ID (derived or explicit) */
|
|
8403
|
-
id:
|
|
8561
|
+
id: z17.string().min(1),
|
|
8404
8562
|
/** Provider display name */
|
|
8405
|
-
name:
|
|
8563
|
+
name: z17.string().min(1),
|
|
8406
8564
|
/** Provider description */
|
|
8407
|
-
description:
|
|
8565
|
+
description: z17.string().optional(),
|
|
8408
8566
|
/** Provider icon URL or emoji */
|
|
8409
|
-
icon:
|
|
8567
|
+
icon: z17.string().optional(),
|
|
8410
8568
|
/** Provider type */
|
|
8411
|
-
type:
|
|
8569
|
+
type: z17.enum(["local", "remote", "transparent"]),
|
|
8412
8570
|
/** OAuth provider URL (for remote providers) */
|
|
8413
|
-
providerUrl:
|
|
8571
|
+
providerUrl: z17.string().url().optional(),
|
|
8414
8572
|
/** Apps using this provider */
|
|
8415
|
-
appIds:
|
|
8573
|
+
appIds: z17.array(z17.string()),
|
|
8416
8574
|
/** App names using this provider */
|
|
8417
|
-
appNames:
|
|
8575
|
+
appNames: z17.array(z17.string()),
|
|
8418
8576
|
/** Scopes required by this provider */
|
|
8419
|
-
scopes:
|
|
8577
|
+
scopes: z17.array(z17.string()),
|
|
8420
8578
|
/** Whether this is the primary/parent provider */
|
|
8421
|
-
isPrimary:
|
|
8579
|
+
isPrimary: z17.boolean(),
|
|
8422
8580
|
/** Whether this provider is optional (can be skipped) */
|
|
8423
|
-
isOptional:
|
|
8581
|
+
isOptional: z17.boolean().default(false)
|
|
8424
8582
|
});
|
|
8425
|
-
var federatedLoginStateSchema =
|
|
8583
|
+
var federatedLoginStateSchema = z17.object({
|
|
8426
8584
|
/** All available providers */
|
|
8427
|
-
providers:
|
|
8585
|
+
providers: z17.array(federatedProviderItemSchema),
|
|
8428
8586
|
/** Primary provider ID (if any) */
|
|
8429
|
-
primaryProviderId:
|
|
8587
|
+
primaryProviderId: z17.string().optional(),
|
|
8430
8588
|
/** Whether user can skip optional providers */
|
|
8431
|
-
allowSkip:
|
|
8589
|
+
allowSkip: z17.boolean().default(true),
|
|
8432
8590
|
/** Pre-selected provider IDs (from previous session) */
|
|
8433
|
-
preselectedProviders:
|
|
8591
|
+
preselectedProviders: z17.array(z17.string()).optional()
|
|
8434
8592
|
});
|
|
8435
|
-
var federatedSelectionSchema =
|
|
8593
|
+
var federatedSelectionSchema = z17.object({
|
|
8436
8594
|
/** Selected provider IDs */
|
|
8437
|
-
selectedProviders:
|
|
8595
|
+
selectedProviders: z17.array(z17.string()),
|
|
8438
8596
|
/** Skipped provider IDs */
|
|
8439
|
-
skippedProviders:
|
|
8597
|
+
skippedProviders: z17.array(z17.string()),
|
|
8440
8598
|
/** Provider-specific metadata */
|
|
8441
|
-
providerMetadata:
|
|
8599
|
+
providerMetadata: z17.record(z17.string(), z17.unknown()).optional()
|
|
8442
8600
|
});
|
|
8443
8601
|
|
|
8444
8602
|
// libs/auth/src/detection/auth-provider-detection.ts
|
|
8445
|
-
import { z as
|
|
8446
|
-
var detectedAuthProviderSchema =
|
|
8447
|
-
id:
|
|
8448
|
-
providerUrl:
|
|
8449
|
-
mode:
|
|
8450
|
-
appIds:
|
|
8451
|
-
scopes:
|
|
8452
|
-
isParentProvider:
|
|
8603
|
+
import { z as z18 } from "@frontmcp/lazy-zod";
|
|
8604
|
+
var detectedAuthProviderSchema = z18.object({
|
|
8605
|
+
id: z18.string(),
|
|
8606
|
+
providerUrl: z18.string().optional(),
|
|
8607
|
+
mode: z18.enum(["public", "static", "transparent", "local", "remote"]),
|
|
8608
|
+
appIds: z18.array(z18.string()),
|
|
8609
|
+
scopes: z18.array(z18.string()),
|
|
8610
|
+
isParentProvider: z18.boolean()
|
|
8453
8611
|
});
|
|
8454
|
-
var authProviderDetectionResultSchema =
|
|
8455
|
-
providers:
|
|
8456
|
-
requiresOrchestration:
|
|
8457
|
-
parentProviderId:
|
|
8458
|
-
childProviderIds:
|
|
8459
|
-
uniqueProviderCount:
|
|
8460
|
-
validationErrors:
|
|
8461
|
-
warnings:
|
|
8612
|
+
var authProviderDetectionResultSchema = z18.object({
|
|
8613
|
+
providers: z18.map(z18.string(), detectedAuthProviderSchema),
|
|
8614
|
+
requiresOrchestration: z18.boolean(),
|
|
8615
|
+
parentProviderId: z18.string().optional(),
|
|
8616
|
+
childProviderIds: z18.array(z18.string()),
|
|
8617
|
+
uniqueProviderCount: z18.number(),
|
|
8618
|
+
validationErrors: z18.array(z18.string()),
|
|
8619
|
+
warnings: z18.array(z18.string())
|
|
8462
8620
|
});
|
|
8463
8621
|
function deriveProviderId(options) {
|
|
8464
8622
|
if (isPublicMode(options)) {
|
|
@@ -8847,43 +9005,43 @@ var AudienceValidator = class _AudienceValidator {
|
|
|
8847
9005
|
};
|
|
8848
9006
|
|
|
8849
9007
|
// libs/auth/src/vault/auth-providers.types.ts
|
|
8850
|
-
import { z as
|
|
8851
|
-
var credentialScopeSchema =
|
|
8852
|
-
var loadingStrategySchema =
|
|
8853
|
-
var getCredentialOptionsSchema =
|
|
8854
|
-
forceRefresh:
|
|
8855
|
-
scopes:
|
|
8856
|
-
timeout:
|
|
9008
|
+
import { z as z19 } from "@frontmcp/lazy-zod";
|
|
9009
|
+
var credentialScopeSchema = z19.enum(["global", "user", "session"]);
|
|
9010
|
+
var loadingStrategySchema = z19.enum(["eager", "lazy"]);
|
|
9011
|
+
var getCredentialOptionsSchema = z19.object({
|
|
9012
|
+
forceRefresh: z19.boolean().optional(),
|
|
9013
|
+
scopes: z19.array(z19.string()).optional(),
|
|
9014
|
+
timeout: z19.number().positive().optional()
|
|
8857
9015
|
}).strict();
|
|
8858
|
-
var credentialProviderConfigSchema =
|
|
8859
|
-
name:
|
|
8860
|
-
description:
|
|
9016
|
+
var credentialProviderConfigSchema = z19.object({
|
|
9017
|
+
name: z19.string().min(1),
|
|
9018
|
+
description: z19.string().optional(),
|
|
8861
9019
|
scope: credentialScopeSchema,
|
|
8862
9020
|
loading: loadingStrategySchema,
|
|
8863
|
-
cacheTtl:
|
|
9021
|
+
cacheTtl: z19.number().nonnegative().optional(),
|
|
8864
9022
|
// Functions validated at runtime, not via Zod (Zod 4 compatibility)
|
|
8865
|
-
factory:
|
|
8866
|
-
refresh:
|
|
8867
|
-
toHeaders:
|
|
8868
|
-
metadata:
|
|
8869
|
-
required:
|
|
9023
|
+
factory: z19.any(),
|
|
9024
|
+
refresh: z19.any().optional(),
|
|
9025
|
+
toHeaders: z19.any().optional(),
|
|
9026
|
+
metadata: z19.record(z19.string(), z19.unknown()).optional(),
|
|
9027
|
+
required: z19.boolean().optional()
|
|
8870
9028
|
}).strict();
|
|
8871
|
-
var authProviderMappingSchema =
|
|
8872
|
-
|
|
8873
|
-
|
|
8874
|
-
name:
|
|
8875
|
-
required:
|
|
8876
|
-
scopes:
|
|
8877
|
-
alias:
|
|
9029
|
+
var authProviderMappingSchema = z19.union([
|
|
9030
|
+
z19.string(),
|
|
9031
|
+
z19.object({
|
|
9032
|
+
name: z19.string().min(1),
|
|
9033
|
+
required: z19.boolean().optional().default(true),
|
|
9034
|
+
scopes: z19.array(z19.string()).optional(),
|
|
9035
|
+
alias: z19.string().optional()
|
|
8878
9036
|
}).strict()
|
|
8879
9037
|
]);
|
|
8880
|
-
var authProvidersVaultOptionsSchema =
|
|
8881
|
-
enabled:
|
|
8882
|
-
useSharedStorage:
|
|
8883
|
-
namespace:
|
|
8884
|
-
defaultCacheTtl:
|
|
8885
|
-
maxCredentialsPerSession:
|
|
8886
|
-
providers:
|
|
9038
|
+
var authProvidersVaultOptionsSchema = z19.object({
|
|
9039
|
+
enabled: z19.boolean().optional(),
|
|
9040
|
+
useSharedStorage: z19.boolean().optional().default(true),
|
|
9041
|
+
namespace: z19.string().optional().default("authproviders:"),
|
|
9042
|
+
defaultCacheTtl: z19.number().nonnegative().optional().default(36e5),
|
|
9043
|
+
maxCredentialsPerSession: z19.number().positive().optional().default(100),
|
|
9044
|
+
providers: z19.array(credentialProviderConfigSchema).optional()
|
|
8887
9045
|
}).strict();
|
|
8888
9046
|
|
|
8889
9047
|
// libs/auth/src/vault/credential-helpers.ts
|
|
@@ -10105,20 +10263,20 @@ function resolveRequiredScopes(denial, mapping, authorities) {
|
|
|
10105
10263
|
}
|
|
10106
10264
|
|
|
10107
10265
|
// libs/auth/src/authorities/authorities.schema.ts
|
|
10108
|
-
import { z as
|
|
10109
|
-
var rbacRolesPolicySchema =
|
|
10110
|
-
all:
|
|
10111
|
-
any:
|
|
10266
|
+
import { z as z20 } from "@frontmcp/lazy-zod";
|
|
10267
|
+
var rbacRolesPolicySchema = z20.object({
|
|
10268
|
+
all: z20.array(z20.string().min(1)).optional(),
|
|
10269
|
+
any: z20.array(z20.string().min(1)).optional()
|
|
10112
10270
|
}).refine((data) => data.all !== void 0 || data.any !== void 0, {
|
|
10113
10271
|
message: 'Roles policy must have at least "all" or "any"'
|
|
10114
10272
|
});
|
|
10115
|
-
var rbacPermissionsPolicySchema =
|
|
10116
|
-
all:
|
|
10117
|
-
any:
|
|
10273
|
+
var rbacPermissionsPolicySchema = z20.object({
|
|
10274
|
+
all: z20.array(z20.string().min(1)).optional(),
|
|
10275
|
+
any: z20.array(z20.string().min(1)).optional()
|
|
10118
10276
|
}).refine((data) => data.all !== void 0 || data.any !== void 0, {
|
|
10119
10277
|
message: 'Permissions policy must have at least "all" or "any"'
|
|
10120
10278
|
});
|
|
10121
|
-
var abacOperatorSchema =
|
|
10279
|
+
var abacOperatorSchema = z20.enum([
|
|
10122
10280
|
"eq",
|
|
10123
10281
|
"neq",
|
|
10124
10282
|
"in",
|
|
@@ -10133,55 +10291,55 @@ var abacOperatorSchema = z19.enum([
|
|
|
10133
10291
|
"exists",
|
|
10134
10292
|
"matches"
|
|
10135
10293
|
]);
|
|
10136
|
-
var abacConditionSchema =
|
|
10137
|
-
path:
|
|
10294
|
+
var abacConditionSchema = z20.object({
|
|
10295
|
+
path: z20.string().min(1),
|
|
10138
10296
|
op: abacOperatorSchema,
|
|
10139
|
-
value:
|
|
10297
|
+
value: z20.unknown()
|
|
10140
10298
|
});
|
|
10141
|
-
var abacPolicySchema =
|
|
10142
|
-
match:
|
|
10143
|
-
conditions:
|
|
10299
|
+
var abacPolicySchema = z20.object({
|
|
10300
|
+
match: z20.record(z20.string(), z20.unknown()).optional(),
|
|
10301
|
+
conditions: z20.array(abacConditionSchema).optional()
|
|
10144
10302
|
}).refine((data) => data.match !== void 0 || data.conditions !== void 0, {
|
|
10145
10303
|
message: 'Attributes policy must have at least "match" or "conditions"'
|
|
10146
10304
|
});
|
|
10147
|
-
var resourceIdRefSchema =
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
|
|
10305
|
+
var resourceIdRefSchema = z20.union([
|
|
10306
|
+
z20.string().min(1),
|
|
10307
|
+
z20.object({ fromInput: z20.string().min(1) }).strict(),
|
|
10308
|
+
z20.object({ fromClaims: z20.string().min(1) }).strict()
|
|
10151
10309
|
]);
|
|
10152
|
-
var rebacPolicySchema =
|
|
10153
|
-
type:
|
|
10154
|
-
resource:
|
|
10310
|
+
var rebacPolicySchema = z20.object({
|
|
10311
|
+
type: z20.string().min(1),
|
|
10312
|
+
resource: z20.string().min(1),
|
|
10155
10313
|
resourceId: resourceIdRefSchema
|
|
10156
10314
|
});
|
|
10157
10315
|
var basePolicyShape = {
|
|
10158
10316
|
roles: rbacRolesPolicySchema.optional(),
|
|
10159
10317
|
permissions: rbacPermissionsPolicySchema.optional(),
|
|
10160
10318
|
attributes: abacPolicySchema.optional(),
|
|
10161
|
-
relationships:
|
|
10162
|
-
custom:
|
|
10163
|
-
guards:
|
|
10164
|
-
operator:
|
|
10319
|
+
relationships: z20.union([rebacPolicySchema, z20.array(rebacPolicySchema)]).optional(),
|
|
10320
|
+
custom: z20.record(z20.string(), z20.unknown()).optional(),
|
|
10321
|
+
guards: z20.array(z20.instanceof(Function)).optional(),
|
|
10322
|
+
operator: z20.enum(["AND", "OR"]).optional()
|
|
10165
10323
|
};
|
|
10166
|
-
var authoritiesPolicySchema =
|
|
10167
|
-
() =>
|
|
10324
|
+
var authoritiesPolicySchema = z20.lazy(
|
|
10325
|
+
() => z20.object({
|
|
10168
10326
|
...basePolicyShape,
|
|
10169
10327
|
not: authoritiesPolicySchema.optional(),
|
|
10170
|
-
anyOf:
|
|
10171
|
-
allOf:
|
|
10328
|
+
anyOf: z20.array(authoritiesPolicySchema).optional(),
|
|
10329
|
+
allOf: z20.array(authoritiesPolicySchema).optional()
|
|
10172
10330
|
})
|
|
10173
10331
|
);
|
|
10174
|
-
var authoritiesMetadataSchema =
|
|
10175
|
-
|
|
10176
|
-
|
|
10332
|
+
var authoritiesMetadataSchema = z20.union([
|
|
10333
|
+
z20.string().min(1),
|
|
10334
|
+
z20.array(z20.string().min(1)).min(1),
|
|
10177
10335
|
authoritiesPolicySchema
|
|
10178
10336
|
]);
|
|
10179
|
-
var authoritiesClaimsMappingSchema =
|
|
10337
|
+
var authoritiesClaimsMappingSchema = z20.record(z20.string(), z20.string().optional()).refine((data) => Object.values(data).some((v) => v !== void 0), {
|
|
10180
10338
|
message: "Claims mapping must have at least one mapping"
|
|
10181
10339
|
});
|
|
10182
|
-
var authoritiesConfigSchema =
|
|
10340
|
+
var authoritiesConfigSchema = z20.object({
|
|
10183
10341
|
claimsMapping: authoritiesClaimsMappingSchema.optional(),
|
|
10184
|
-
profiles:
|
|
10342
|
+
profiles: z20.record(z20.string().min(1), authoritiesPolicySchema).optional()
|
|
10185
10343
|
});
|
|
10186
10344
|
|
|
10187
10345
|
// libs/auth/src/authorities/authorities.evaluator.ts
|
|
@@ -10861,6 +11019,7 @@ export {
|
|
|
10861
11019
|
CredentialProviderAlreadyRegisteredError,
|
|
10862
11020
|
CredentialStorageError,
|
|
10863
11021
|
CredentialsAccessorImpl,
|
|
11022
|
+
DEFAULT_INCREMENTAL_TICKET_TTL_MS,
|
|
10864
11023
|
DEFAULT_RESUME_TTL_MS,
|
|
10865
11024
|
DEFAULT_THEME,
|
|
10866
11025
|
DcrClientRegistry,
|
|
@@ -10883,6 +11042,8 @@ export {
|
|
|
10883
11042
|
InMemoryStoreRequiredError,
|
|
10884
11043
|
InvalidClientIdUrlError,
|
|
10885
11044
|
JwksService,
|
|
11045
|
+
JwtSecretRequiredError,
|
|
11046
|
+
JwtSecretWeakError,
|
|
10886
11047
|
LazyCredentialLoader,
|
|
10887
11048
|
NoProviderIdError,
|
|
10888
11049
|
NullOrchestratedAuthAccessor,
|
|
@@ -11053,6 +11214,7 @@ export {
|
|
|
11053
11214
|
isSoonExpiring,
|
|
11054
11215
|
isSoonExpiringProvider,
|
|
11055
11216
|
isSqliteTokenStorage,
|
|
11217
|
+
isStaticMode,
|
|
11056
11218
|
isTransparentMode,
|
|
11057
11219
|
jsonWebKeySetSchema,
|
|
11058
11220
|
jwkParametersSchema,
|
|
@@ -11104,6 +11266,7 @@ export {
|
|
|
11104
11266
|
sessionIdPayloadSchema,
|
|
11105
11267
|
sessionJwtPayloadSchema,
|
|
11106
11268
|
signCredentialResumeToken,
|
|
11269
|
+
signIncrementalAuthTicket,
|
|
11107
11270
|
signSession,
|
|
11108
11271
|
skippedAppBehaviorSchema,
|
|
11109
11272
|
sseTransportStateSchema,
|
|
@@ -11111,6 +11274,7 @@ export {
|
|
|
11111
11274
|
startNextProvider,
|
|
11112
11275
|
statefulHttpTransportStateSchema,
|
|
11113
11276
|
statelessHttpTransportStateSchema,
|
|
11277
|
+
staticAuthOptionsSchema,
|
|
11114
11278
|
storedSessionSchema,
|
|
11115
11279
|
streamableHttpTransportStateSchema,
|
|
11116
11280
|
toEpochSeconds,
|
|
@@ -11132,6 +11296,7 @@ export {
|
|
|
11132
11296
|
vaultConsentRecordSchema,
|
|
11133
11297
|
vaultFederatedRecordSchema,
|
|
11134
11298
|
verifyCredentialResumeToken,
|
|
11299
|
+
verifyIncrementalAuthTicket,
|
|
11135
11300
|
verifyOrParseSession,
|
|
11136
11301
|
verifyPkce,
|
|
11137
11302
|
verifySession,
|