@frontmcp/auth 1.10.16 → 1.11.0-rc.2

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.
Files changed (175) hide show
  1. package/browser/authorities/authorities.context.mjs +115 -0
  2. package/browser/authorities/authorities.engine.mjs +272 -0
  3. package/browser/authorities/authorities.errors.mjs +59 -0
  4. package/browser/authorities/authorities.evaluator.mjs +225 -0
  5. package/browser/authorities/authorities.metadata-augment.mjs +18 -0
  6. package/browser/authorities/authorities.registry.mjs +112 -0
  7. package/browser/authorities/authorities.schema.mjs +92 -0
  8. package/browser/authorities/authorities.scope-mapping.mjs +30 -0
  9. package/browser/authorities/authorities.validation.mjs +208 -0
  10. package/browser/authorities/index.mjs +43 -0
  11. package/browser/authorization/authorization.class.mjs +252 -0
  12. package/browser/authorization/authorization.types.mjs +64 -0
  13. package/browser/authorization/dcr-client.registry.mjs +222 -0
  14. package/browser/authorization/index.mjs +41 -0
  15. package/browser/authorization/orchestrated.accessor.mjs +86 -0
  16. package/browser/authorization/orchestrated.authorization.mjs +289 -0
  17. package/browser/authorization/public.authorization.mjs +124 -0
  18. package/browser/authorization/transparent.authorization.mjs +130 -0
  19. package/browser/cimd/cimd-redis.cache.mjs +231 -0
  20. package/browser/cimd/cimd.cache.mjs +215 -0
  21. package/browser/cimd/cimd.errors.mjs +142 -0
  22. package/browser/cimd/cimd.logger.mjs +15 -0
  23. package/browser/cimd/cimd.service.mjs +376 -0
  24. package/browser/cimd/cimd.types.mjs +228 -0
  25. package/browser/cimd/cimd.validator.mjs +217 -0
  26. package/browser/cimd/index.mjs +63 -0
  27. package/browser/common/auth-logger.interface.mjs +14 -0
  28. package/browser/common/index.mjs +6 -0
  29. package/browser/common/jwt.types.mjs +38 -0
  30. package/browser/common/session-user.types.mjs +0 -0
  31. package/browser/common/session.types.mjs +58 -0
  32. package/browser/common/zod-utils.mjs +0 -0
  33. package/browser/consent/consent.types.mjs +94 -0
  34. package/browser/consent/index.mjs +17 -0
  35. package/browser/context/frontmcp-auth-context.factory.mjs +29 -0
  36. package/browser/context/frontmcp-auth-context.impl.mjs +112 -0
  37. package/browser/context/index.mjs +7 -0
  38. package/browser/detection/auth-provider-detection.mjs +176 -0
  39. package/browser/detection/index.mjs +19 -0
  40. package/browser/errors/auth-internal.error.mjs +42 -0
  41. package/browser/errors/auth-internal.errors.mjs +150 -0
  42. package/browser/errors/index.mjs +53 -0
  43. package/browser/fetch/fetch-credential-middleware.mjs +91 -0
  44. package/browser/fetch/index.mjs +19 -0
  45. package/browser/index.mjs +573 -0
  46. package/browser/jwks/index.mjs +9 -0
  47. package/browser/jwks/jose.loader.mjs +28 -0
  48. package/browser/jwks/jwks.service.mjs +521 -0
  49. package/browser/jwks/jwks.utils.mjs +33 -0
  50. package/browser/options/app-auth.schema.mjs +18 -0
  51. package/browser/options/index.mjs +89 -0
  52. package/browser/options/orchestrated.schema.mjs +128 -0
  53. package/browser/options/public.schema.mjs +39 -0
  54. package/browser/options/schema.mjs +16 -0
  55. package/browser/options/shared.schemas.mjs +506 -0
  56. package/browser/options/static.schema.mjs +41 -0
  57. package/browser/options/transparent.schema.mjs +43 -0
  58. package/browser/options/utils.mjs +47 -0
  59. package/browser/people/index.mjs +15 -0
  60. package/browser/people/loopback-token.auth.mjs +115 -0
  61. package/browser/people/people-auth.options.mjs +37 -0
  62. package/browser/session/authorization-vault.mjs +279 -0
  63. package/browser/session/authorization.store.mjs +336 -0
  64. package/browser/session/consent.store.mjs +34 -0
  65. package/browser/session/credential-resume-link.mjs +43 -0
  66. package/browser/session/credentials-accessor.impl.mjs +54 -0
  67. package/browser/session/credentials-accessor.mjs +5 -0
  68. package/browser/session/encrypted-authorization-vault.mjs +405 -0
  69. package/browser/session/federated-auth.session.mjs +176 -0
  70. package/browser/session/incremental-auth-ticket.mjs +42 -0
  71. package/browser/session/index.mjs +266 -0
  72. package/browser/session/orchestrated-token.crypto.mjs +47 -0
  73. package/browser/session/orchestrated-token.store.mjs +286 -0
  74. package/browser/session/pending-login.mjs +37 -0
  75. package/browser/session/redis-session.store.mjs +255 -0
  76. package/browser/session/secure-store-accessor.impl.mjs +78 -0
  77. package/browser/session/secure-store-accessor.mjs +5 -0
  78. package/browser/session/secure-store-backends.mjs +111 -0
  79. package/browser/session/secure-store.factory.mjs +77 -0
  80. package/browser/session/session-credential-vault.factory.mjs +18 -0
  81. package/browser/session/session-credential-vault.mjs +243 -0
  82. package/browser/session/session-crypto.mjs +39 -0
  83. package/browser/session/session-rate-limiter.mjs +126 -0
  84. package/browser/session/session.transport.mjs +16 -0
  85. package/browser/session/signin-binding.mjs +30 -0
  86. package/browser/session/storage/in-memory-authorization-vault.mjs +28 -0
  87. package/browser/session/storage/index.mjs +14 -0
  88. package/browser/session/storage/storage-authorization-vault.mjs +301 -0
  89. package/browser/session/storage/storage-token-store.mjs +83 -0
  90. package/browser/session/storage-authorization.store.mjs +134 -0
  91. package/browser/session/storage-consent.store.mjs +33 -0
  92. package/browser/session/storage-federated-auth.session.mjs +55 -0
  93. package/browser/session/storage-orchestrated-token.store.mjs +197 -0
  94. package/browser/session/token-storage.factory.mjs +58 -0
  95. package/browser/session/token.refresh.mjs +36 -0
  96. package/browser/session/token.vault.mjs +61 -0
  97. package/browser/session/transport-session.types.mjs +108 -0
  98. package/browser/session/utils/auth-token.utils.mjs +58 -0
  99. package/browser/session/utils/index.mjs +23 -0
  100. package/browser/session/utils/session-crypto.utils.mjs +49 -0
  101. package/browser/session/utils/tiny-ttl-cache.mjs +46 -0
  102. package/browser/session/vault-encryption.mjs +187 -0
  103. package/browser/session/vercel-kv-session.store.mjs +230 -0
  104. package/browser/shared-server/index.mjs +17 -0
  105. package/browser/shared-server/shared-server-identity.mjs +55 -0
  106. package/browser/ui/base-layout.mjs +184 -0
  107. package/browser/ui/index.mjs +51 -0
  108. package/browser/ui/local-login.helper.mjs +46 -0
  109. package/browser/ui/templates.mjs +482 -0
  110. package/browser/utils/audience.validator.mjs +110 -0
  111. package/browser/utils/authorization-id.utils.mjs +10 -0
  112. package/browser/utils/index.mjs +45 -0
  113. package/browser/utils/redirect-uri.utils.mjs +22 -0
  114. package/browser/utils/scope-grant.utils.mjs +36 -0
  115. package/browser/utils/token-scopes.utils.mjs +12 -0
  116. package/browser/utils/www-authenticate.utils.mjs +164 -0
  117. package/browser/vault/auth-providers.accessor.impl.mjs +236 -0
  118. package/browser/vault/auth-providers.accessor.mjs +5 -0
  119. package/browser/vault/auth-providers.registry.mjs +140 -0
  120. package/browser/vault/auth-providers.types.mjs +47 -0
  121. package/browser/vault/auth-providers.vault.mjs +206 -0
  122. package/browser/vault/credential-cache.mjs +187 -0
  123. package/browser/vault/credential-helpers.mjs +15 -0
  124. package/browser/vault/credential-loaders/eager-loader.mjs +91 -0
  125. package/browser/vault/credential-loaders/lazy-loader.mjs +120 -0
  126. package/browser/vault/index.mjs +35 -0
  127. package/cimd/cimd.types.d.ts +1 -1
  128. package/cimd/cimd.types.d.ts.map +1 -1
  129. package/common/jwt.types.d.ts +1 -1
  130. package/common/jwt.types.d.ts.map +1 -1
  131. package/common/session.types.d.ts +9 -1
  132. package/common/session.types.d.ts.map +1 -1
  133. package/consent/consent.types.d.ts +1 -1
  134. package/consent/consent.types.d.ts.map +1 -1
  135. package/detection/auth-provider-detection.d.ts +1 -1
  136. package/detection/auth-provider-detection.d.ts.map +1 -1
  137. package/errors/auth-internal.errors.d.ts +6 -0
  138. package/errors/auth-internal.errors.d.ts.map +1 -1
  139. package/errors/index.d.ts +1 -1
  140. package/errors/index.d.ts.map +1 -1
  141. package/esm/index.mjs +2 -2
  142. package/esm/package.json +21 -5
  143. package/index.d.ts +5 -1
  144. package/index.d.ts.map +1 -1
  145. package/index.js +2 -2
  146. package/options/app-auth.schema.d.ts +19 -1
  147. package/options/app-auth.schema.d.ts.map +1 -1
  148. package/options/orchestrated.schema.d.ts +37 -1
  149. package/options/orchestrated.schema.d.ts.map +1 -1
  150. package/options/public.schema.d.ts +1 -1
  151. package/options/public.schema.d.ts.map +1 -1
  152. package/options/schema.d.ts +19 -1
  153. package/options/schema.d.ts.map +1 -1
  154. package/options/shared.schemas.d.ts +10 -14
  155. package/options/shared.schemas.d.ts.map +1 -1
  156. package/options/static.schema.d.ts +1 -1
  157. package/options/static.schema.d.ts.map +1 -1
  158. package/options/transparent.schema.d.ts +1 -1
  159. package/options/transparent.schema.d.ts.map +1 -1
  160. package/package.json +21 -5
  161. package/people/index.d.ts +3 -0
  162. package/people/index.d.ts.map +1 -0
  163. package/people/loopback-token.auth.d.ts +75 -0
  164. package/people/loopback-token.auth.d.ts.map +1 -0
  165. package/people/people-auth.options.d.ts +36 -0
  166. package/people/people-auth.options.d.ts.map +1 -0
  167. package/session/authorization-vault.d.ts +1 -1
  168. package/session/authorization-vault.d.ts.map +1 -1
  169. package/session/encrypted-authorization-vault.d.ts +1 -1
  170. package/session/encrypted-authorization-vault.d.ts.map +1 -1
  171. package/session/secure-store.factory.d.ts.map +1 -1
  172. package/shared-server/index.d.ts +3 -0
  173. package/shared-server/index.d.ts.map +1 -0
  174. package/shared-server/shared-server-identity.d.ts +26 -0
  175. package/shared-server/shared-server-identity.d.ts.map +1 -0
@@ -0,0 +1,41 @@
1
+ // libs/auth/src/options/static.schema.ts
2
+ import { internalZ as z } from "@frontmcp/lazy-zod";
3
+ import { publicAccessConfigSchema } from "./shared.schemas.mjs";
4
+ var staticAuthOptionsSchema = z.object({
5
+ mode: z.literal("static"),
6
+ /**
7
+ * Accepted credentials. Compared against the presented one in constant time,
8
+ * over SHA-256 digests so neither the value nor its length leaks by timing.
9
+ *
10
+ * Read these from the environment \u2014 never commit them.
11
+ */
12
+ tokens: z.array(z.string().min(1)).min(1),
13
+ /**
14
+ * Request header carrying the credential.
15
+ * @default 'authorization'
16
+ */
17
+ header: z.string().min(1).default("authorization"),
18
+ /**
19
+ * Scheme prefix to strip before comparing, matched case-insensitively. Set to
20
+ * an empty string for headers that carry a bare token (e.g. `x-api-key`).
21
+ * @default 'Bearer'
22
+ */
23
+ scheme: z.string().default("Bearer"),
24
+ /**
25
+ * Scopes granted to a request that presents a valid token.
26
+ * @default ['static']
27
+ */
28
+ scopes: z.array(z.string()).default(["static"]),
29
+ /**
30
+ * Realm reported in the `WWW-Authenticate` challenge on failure.
31
+ * @default 'mcp'
32
+ */
33
+ realm: z.string().default("mcp"),
34
+ /**
35
+ * Tool/prompt access configuration, same shape the other modes accept.
36
+ */
37
+ publicAccess: publicAccessConfigSchema.optional()
38
+ });
39
+ export {
40
+ staticAuthOptionsSchema
41
+ };
@@ -0,0 +1,43 @@
1
+ // libs/auth/src/options/transparent.schema.ts
2
+ import { internalZ as z } from "@frontmcp/lazy-zod";
3
+ import { flatRemoteProviderFields, publicAccessConfigSchema } from "./shared.schemas.mjs";
4
+ var transparentAuthOptionsSchema = z.object({
5
+ mode: z.literal("transparent"),
6
+ /**
7
+ * Flattened remote provider fields (provider, clientId, clientSecret, scopes, providerConfig)
8
+ */
9
+ ...flatRemoteProviderFields,
10
+ /**
11
+ * Expected token audience
12
+ * If not set, defaults to the resource URL
13
+ */
14
+ expectedAudience: z.union([z.string(), z.array(z.string())]).optional(),
15
+ /**
16
+ * Require an `aud` claim (reject audience-less tokens). Defaults to `false`
17
+ * for IdP compatibility; set `true` to reject tokens with no audience.
18
+ */
19
+ requireAudience: z.boolean().optional(),
20
+ /**
21
+ * Required scopes for access
22
+ * Empty array means any valid token is accepted
23
+ * @default []
24
+ */
25
+ requiredScopes: z.array(z.string()).default([]),
26
+ /**
27
+ * Allow anonymous fallback when no token is provided
28
+ * @default false
29
+ */
30
+ allowAnonymous: z.boolean().default(false),
31
+ /**
32
+ * Scopes granted to anonymous sessions (when allowAnonymous=true)
33
+ * @default ['anonymous']
34
+ */
35
+ anonymousScopes: z.array(z.string()).default(["anonymous"]),
36
+ /**
37
+ * Public access config for anonymous users (when allowAnonymous=true)
38
+ */
39
+ publicAccess: publicAccessConfigSchema.optional()
40
+ });
41
+ export {
42
+ transparentAuthOptionsSchema
43
+ };
@@ -0,0 +1,47 @@
1
+ // libs/auth/src/options/utils.ts
2
+ import { authOptionsSchema } from "./schema.mjs";
3
+ function parseAuthOptions(input) {
4
+ return authOptionsSchema.parse(input);
5
+ }
6
+ function isPublicMode(options) {
7
+ return options.mode === "public";
8
+ }
9
+ function isStaticMode(options) {
10
+ return options.mode === "static";
11
+ }
12
+ function isTransparentMode(options) {
13
+ return options.mode === "transparent";
14
+ }
15
+ function isLocalMode(options) {
16
+ return options.mode === "local";
17
+ }
18
+ function isRemoteMode(options) {
19
+ return options.mode === "remote";
20
+ }
21
+ function isOrchestratedMode(options) {
22
+ return options.mode === "local" || options.mode === "remote";
23
+ }
24
+ function isOrchestratedLocal(options) {
25
+ return options.mode === "local";
26
+ }
27
+ function isOrchestratedRemote(options) {
28
+ return options.mode === "remote";
29
+ }
30
+ function allowsPublicAccess(options) {
31
+ if (options.mode === "public") return true;
32
+ if (options.mode === "transparent") return options.allowAnonymous;
33
+ if (options.mode === "local" || options.mode === "remote") return options.allowDefaultPublic;
34
+ return false;
35
+ }
36
+ export {
37
+ allowsPublicAccess,
38
+ isLocalMode,
39
+ isOrchestratedLocal,
40
+ isOrchestratedMode,
41
+ isOrchestratedRemote,
42
+ isPublicMode,
43
+ isRemoteMode,
44
+ isStaticMode,
45
+ isTransparentMode,
46
+ parseAuthOptions
47
+ };
@@ -0,0 +1,15 @@
1
+ // libs/auth/src/people/index.ts
2
+ import {
3
+ peopleAuthOptionsSchema
4
+ } from "./people-auth.options.mjs";
5
+ import {
6
+ LoopbackTokenAuth,
7
+ PEOPLE_SESSION_COOKIE,
8
+ peopleSessionCookie
9
+ } from "./loopback-token.auth.mjs";
10
+ export {
11
+ LoopbackTokenAuth,
12
+ PEOPLE_SESSION_COOKIE,
13
+ peopleAuthOptionsSchema,
14
+ peopleSessionCookie
15
+ };
@@ -0,0 +1,115 @@
1
+ // libs/auth/src/people/loopback-token.auth.ts
2
+ import { base64urlEncode, randomBytes, sha256, timingSafeEqual } from "@frontmcp/utils";
3
+ var PEOPLE_SESSION_COOKIE = "frontmcp_people";
4
+ var INVALID = { ok: false, reason: "invalid" };
5
+ var LOCKED = { ok: false, reason: "locked" };
6
+ var MAX_TRACKED_CLIENTS = 1024;
7
+ function newSecret() {
8
+ return base64urlEncode(randomBytes(32));
9
+ }
10
+ function matches(presented, digest) {
11
+ return timingSafeEqual(sha256(presented), digest);
12
+ }
13
+ function unexpired(secrets) {
14
+ const now = Date.now();
15
+ return secrets.filter((secret) => secret.expiresAt > now);
16
+ }
17
+ var LoopbackTokenAuth = class {
18
+ constructor(options) {
19
+ this.options = options;
20
+ const token = newSecret();
21
+ this.token = token;
22
+ this.tokenDigest = sha256(token);
23
+ }
24
+ options;
25
+ token;
26
+ tokenDigest;
27
+ codes = [];
28
+ sessions = [];
29
+ failures = /* @__PURE__ */ new Map();
30
+ /** The token, the first time it is asked for: the server prints it at startup, and nothing can read it after. */
31
+ takeToken() {
32
+ const token = this.token;
33
+ this.token = void 0;
34
+ return token;
35
+ }
36
+ /**
37
+ * A one-time sign-in code, for a caller this process already trusts, such as a tool. A code made for a `subject`
38
+ * signs the person in for that subject only; a code without one, such as the token's, for none.
39
+ */
40
+ createCode(options = {}) {
41
+ const code = newSecret();
42
+ const expiresAt = Date.now() + this.options.codeTtlMs;
43
+ const { subject } = options;
44
+ this.codes = [...unexpired(this.codes), { digest: sha256(code), expiresAt, ...subject ? { subject } : {} }];
45
+ return { code, expiresAt };
46
+ }
47
+ /** A one-time sign-in code for the holder of the token. */
48
+ exchangeToken(presented, client) {
49
+ if (this.isLocked(client)) return LOCKED;
50
+ if (presented === void 0 || !matches(presented, this.tokenDigest)) return this.refuse(client);
51
+ this.failures.delete(client);
52
+ return { ok: true, ...this.createCode() };
53
+ }
54
+ /** A session for the holder of a code; the code is spent. */
55
+ exchangeCode(presented, client) {
56
+ if (this.isLocked(client)) return LOCKED;
57
+ this.codes = unexpired(this.codes);
58
+ const index = presented === void 0 ? -1 : this.codes.findIndex((code) => matches(presented, code.digest));
59
+ if (index === -1) return this.refuse(client);
60
+ const [{ subject }] = this.codes.splice(index, 1);
61
+ this.failures.delete(client);
62
+ const cookieValue = newSecret();
63
+ const expiresAt = Date.now() + this.options.sessionTtlMs;
64
+ this.sessions = [
65
+ ...unexpired(this.sessions),
66
+ { digest: sha256(cookieValue), expiresAt, ...subject ? { subject } : {} }
67
+ ];
68
+ return { ok: true, cookieValue, expiresAt };
69
+ }
70
+ verifySession(presented) {
71
+ if (!presented) return void 0;
72
+ this.sessions = unexpired(this.sessions);
73
+ const session = this.sessions.find((stored) => matches(presented, stored.digest));
74
+ if (!session) return void 0;
75
+ return session.subject ? { expiresAt: session.expiresAt, subject: session.subject } : { expiresAt: session.expiresAt };
76
+ }
77
+ endSession(presented) {
78
+ if (!presented) return;
79
+ this.sessions = this.sessions.filter((stored) => !matches(presented, stored.digest));
80
+ }
81
+ isLocked(client) {
82
+ return (this.failures.get(client)?.lockedUntil ?? 0) > Date.now();
83
+ }
84
+ refuse(client) {
85
+ const now = Date.now();
86
+ const { maxFailedAttempts, lockoutMs } = this.options;
87
+ const previous = this.failures.get(client);
88
+ const count = previous && now - previous.lastAt <= lockoutMs ? previous.count + 1 : 1;
89
+ const locked = count >= maxFailedAttempts;
90
+ if (!previous && this.failures.size >= MAX_TRACKED_CLIENTS) this.forgetIdleClients(now);
91
+ this.failures.set(client, { count: locked ? 0 : count, lastAt: now, lockedUntil: locked ? now + lockoutMs : 0 });
92
+ return locked ? LOCKED : INVALID;
93
+ }
94
+ forgetIdleClients(now) {
95
+ for (const [client, failures] of this.failures) {
96
+ if (failures.lockedUntil <= now && now - failures.lastAt > this.options.lockoutMs) this.failures.delete(client);
97
+ }
98
+ }
99
+ };
100
+ function peopleSessionCookie(value, options) {
101
+ return {
102
+ name: PEOPLE_SESSION_COOKIE,
103
+ value,
104
+ path: options.path,
105
+ httpOnly: true,
106
+ sameSite: "strict",
107
+ secure: options.secure,
108
+ maxAge: Math.floor(options.maxAgeMs / 1e3)
109
+ };
110
+ }
111
+ export {
112
+ LoopbackTokenAuth,
113
+ PEOPLE_SESSION_COOKIE,
114
+ peopleSessionCookie
115
+ };
@@ -0,0 +1,37 @@
1
+ // libs/auth/src/people/people-auth.options.ts
2
+ import { internalZ as z } from "@frontmcp/lazy-zod";
3
+ var MINUTE_MS = 6e4;
4
+ function milliseconds(field) {
5
+ return z.number({ message: `${field} must be a number of milliseconds` }).int(`${field} must be a whole number of milliseconds`).positive(`${field} must be greater than 0`);
6
+ }
7
+ function createPeopleAuthOptionsSchema() {
8
+ const loopbackToken = z.object({
9
+ mode: z.literal("loopback-token"),
10
+ codeTtlMs: milliseconds("codeTtlMs").max(10 * MINUTE_MS, "codeTtlMs must be at most 600000 (10 minutes): a sign-in code is for one hand-off").optional(),
11
+ sessionTtlMs: milliseconds("sessionTtlMs").optional(),
12
+ maxFailedAttempts: z.number({ message: "maxFailedAttempts must be a number" }).int("maxFailedAttempts must be a whole number").positive("maxFailedAttempts must be greater than 0").optional(),
13
+ lockoutMs: milliseconds("lockoutMs").optional(),
14
+ cookiePath: z.string().startsWith("/", 'cookiePath must start with "/"').optional()
15
+ }).strict();
16
+ return z.union([z.literal("loopback-token"), loopbackToken], {
17
+ message: "http.auth.people must be 'loopback-token' or { mode: 'loopback-token', ... }"
18
+ }).transform((value) => {
19
+ const settings = typeof value === "string" ? {} : value;
20
+ return {
21
+ mode: "loopback-token",
22
+ codeTtlMs: settings.codeTtlMs ?? MINUTE_MS,
23
+ sessionTtlMs: settings.sessionTtlMs ?? 12 * 60 * MINUTE_MS,
24
+ maxFailedAttempts: settings.maxFailedAttempts ?? 5,
25
+ lockoutMs: settings.lockoutMs ?? MINUTE_MS,
26
+ cookiePath: settings.cookiePath ?? "/"
27
+ };
28
+ });
29
+ }
30
+ var schema;
31
+ function peopleAuthOptionsSchema() {
32
+ schema ??= createPeopleAuthOptionsSchema();
33
+ return schema;
34
+ }
35
+ export {
36
+ peopleAuthOptionsSchema
37
+ };
@@ -0,0 +1,279 @@
1
+ // libs/auth/src/session/authorization-vault.ts
2
+ import { internalZ as z } from "@frontmcp/lazy-zod";
3
+ var credentialTypeSchema = z.enum([
4
+ "oauth",
5
+ // OAuth 2.0 tokens
6
+ "api_key",
7
+ // API key (header or query param)
8
+ "basic",
9
+ // Basic auth (username:password)
10
+ "bearer",
11
+ // Bearer token (static)
12
+ "private_key",
13
+ // Private key for signing (JWT, etc.)
14
+ "mtls",
15
+ // Mutual TLS certificate
16
+ "custom",
17
+ // Custom credential type
18
+ "ssh_key",
19
+ // SSH key for authentication
20
+ "service_account",
21
+ // Cloud provider service accounts
22
+ "oauth_pkce"
23
+ // OAuth 2.0 with PKCE for public clients
24
+ ]);
25
+ var oauthCredentialSchema = z.object({
26
+ type: z.literal("oauth"),
27
+ /** Access token */
28
+ accessToken: z.string(),
29
+ /** Refresh token (optional) */
30
+ refreshToken: z.string().optional(),
31
+ /** Token type (usually 'Bearer') */
32
+ tokenType: z.string().default("Bearer"),
33
+ /** Token expiration timestamp (epoch ms) */
34
+ expiresAt: z.number().optional(),
35
+ /** Granted scopes */
36
+ scopes: z.array(z.string()).default([]),
37
+ /** ID token for OIDC (optional) */
38
+ idToken: z.string().optional()
39
+ });
40
+ var apiKeyCredentialSchema = z.object({
41
+ type: z.literal("api_key"),
42
+ /** The API key value */
43
+ key: z.string().min(1),
44
+ /** Header name to use (e.g., 'X-API-Key', 'Authorization') */
45
+ headerName: z.string().default("X-API-Key"),
46
+ /** Prefix for the header value (e.g., 'Bearer ', 'Api-Key ') */
47
+ headerPrefix: z.string().optional(),
48
+ /** Alternative: send as query parameter */
49
+ queryParam: z.string().optional()
50
+ });
51
+ var basicAuthCredentialSchema = z.object({
52
+ type: z.literal("basic"),
53
+ /** Username */
54
+ username: z.string().min(1),
55
+ /** Password */
56
+ password: z.string(),
57
+ /** Pre-computed base64 encoded value (optional, for caching) */
58
+ encodedValue: z.string().optional()
59
+ });
60
+ var bearerCredentialSchema = z.object({
61
+ type: z.literal("bearer"),
62
+ /** The bearer token value */
63
+ token: z.string().min(1),
64
+ /** Token expiration (optional, for static tokens that expire) */
65
+ expiresAt: z.number().optional()
66
+ });
67
+ var privateKeyCredentialSchema = z.object({
68
+ type: z.literal("private_key"),
69
+ /** Key format */
70
+ format: z.enum(["pem", "jwk", "pkcs8", "pkcs12"]),
71
+ /** The key data (PEM string or JWK JSON) */
72
+ keyData: z.string(),
73
+ /** Key ID (for JWK) */
74
+ keyId: z.string().optional(),
75
+ /** Algorithm to use for signing */
76
+ algorithm: z.string().optional(),
77
+ /** Passphrase if key is encrypted */
78
+ passphrase: z.string().optional(),
79
+ /** Associated certificate (for mTLS) */
80
+ certificate: z.string().optional()
81
+ });
82
+ var mtlsCredentialSchema = z.object({
83
+ type: z.literal("mtls"),
84
+ /** Client certificate (PEM format) */
85
+ certificate: z.string(),
86
+ /** Private key (PEM format) */
87
+ privateKey: z.string(),
88
+ /** Passphrase if private key is encrypted */
89
+ passphrase: z.string().optional(),
90
+ /** CA certificate chain (optional) */
91
+ caCertificate: z.string().optional()
92
+ });
93
+ var customCredentialSchema = z.object({
94
+ type: z.literal("custom"),
95
+ /** Custom type identifier */
96
+ customType: z.string().min(1),
97
+ /** Arbitrary credential data */
98
+ data: z.record(z.string(), z.unknown()),
99
+ /** Headers to include in requests */
100
+ headers: z.record(z.string(), z.string()).optional()
101
+ });
102
+ var sshKeyCredentialSchema = z.object({
103
+ type: z.literal("ssh_key"),
104
+ /** Private key (PEM format) */
105
+ privateKey: z.string().min(1),
106
+ /** Public key (optional, can be derived from private key) */
107
+ publicKey: z.string().optional(),
108
+ /** Passphrase if private key is encrypted */
109
+ passphrase: z.string().optional(),
110
+ /** Key type */
111
+ keyType: z.enum(["rsa", "ed25519", "ecdsa", "dsa"]).default("ed25519"),
112
+ /** Key fingerprint (SHA256 hash) */
113
+ fingerprint: z.string().optional(),
114
+ /** Username for SSH connections */
115
+ username: z.string().optional()
116
+ });
117
+ var serviceAccountCredentialSchema = z.object({
118
+ type: z.literal("service_account"),
119
+ /** Cloud provider */
120
+ provider: z.enum(["gcp", "aws", "azure", "custom"]),
121
+ /** Raw credentials (JSON key file content, access keys, etc.) */
122
+ credentials: z.record(z.string(), z.unknown()),
123
+ /** Project/Account ID */
124
+ projectId: z.string().optional(),
125
+ /** Region for regional services */
126
+ region: z.string().optional(),
127
+ /** AWS: Role ARN to assume */
128
+ assumeRoleArn: z.string().optional(),
129
+ /** AWS: External ID for cross-account access */
130
+ externalId: z.string().optional(),
131
+ /** Service account email (GCP) or ARN (AWS) */
132
+ serviceAccountId: z.string().optional(),
133
+ /** Expiration timestamp for temporary credentials */
134
+ expiresAt: z.number().optional()
135
+ });
136
+ var pkceOAuthCredentialSchema = z.object({
137
+ type: z.literal("oauth_pkce"),
138
+ /** Access token */
139
+ accessToken: z.string(),
140
+ /** Refresh token (optional) */
141
+ refreshToken: z.string().optional(),
142
+ /** Token type (usually 'Bearer') */
143
+ tokenType: z.string().default("Bearer"),
144
+ /** Token expiration timestamp (epoch ms) */
145
+ expiresAt: z.number().optional(),
146
+ /** Granted scopes */
147
+ scopes: z.array(z.string()).default([]),
148
+ /** ID token for OIDC (optional) */
149
+ idToken: z.string().optional(),
150
+ /** Authorization server issuer */
151
+ issuer: z.string().optional()
152
+ });
153
+ var credentialSchema = z.discriminatedUnion("type", [
154
+ oauthCredentialSchema,
155
+ apiKeyCredentialSchema,
156
+ basicAuthCredentialSchema,
157
+ bearerCredentialSchema,
158
+ privateKeyCredentialSchema,
159
+ mtlsCredentialSchema,
160
+ customCredentialSchema,
161
+ sshKeyCredentialSchema,
162
+ serviceAccountCredentialSchema,
163
+ pkceOAuthCredentialSchema
164
+ ]);
165
+ var appCredentialSchema = z.object({
166
+ /** App ID this credential belongs to */
167
+ appId: z.string().min(1),
168
+ /** Provider ID within the app (for apps with multiple auth providers) */
169
+ providerId: z.string().min(1),
170
+ /** The credential data */
171
+ credential: credentialSchema,
172
+ /** Timestamp when credential was acquired */
173
+ acquiredAt: z.number(),
174
+ /** Timestamp when credential was last used */
175
+ lastUsedAt: z.number().optional(),
176
+ /** Credential expiration (if applicable) */
177
+ expiresAt: z.number().optional(),
178
+ /** Whether this credential is currently valid */
179
+ isValid: z.boolean().default(true),
180
+ /** Error message if credential is invalid */
181
+ invalidReason: z.string().optional(),
182
+ /** User info associated with this credential */
183
+ userInfo: z.object({
184
+ sub: z.string().optional(),
185
+ email: z.string().optional(),
186
+ name: z.string().optional()
187
+ }).optional(),
188
+ /** Metadata for tracking/debugging */
189
+ metadata: z.record(z.string(), z.unknown()).optional()
190
+ });
191
+ var vaultConsentRecordSchema = z.object({
192
+ /** Whether consent was enabled */
193
+ enabled: z.boolean(),
194
+ /** Selected tool IDs (user approved these) */
195
+ selectedToolIds: z.array(z.string()),
196
+ /** Available tool IDs at time of consent */
197
+ availableToolIds: z.array(z.string()),
198
+ /** Timestamp when consent was given */
199
+ consentedAt: z.number(),
200
+ /** Consent version for tracking changes */
201
+ version: z.string().default("1.0")
202
+ });
203
+ var vaultFederatedRecordSchema = z.object({
204
+ /** Provider IDs that were selected */
205
+ selectedProviderIds: z.array(z.string()),
206
+ /** Provider IDs that were skipped (can be authorized later) */
207
+ skippedProviderIds: z.array(z.string()),
208
+ /** Primary provider ID */
209
+ primaryProviderId: z.string().optional(),
210
+ /** Timestamp when federated login was completed */
211
+ completedAt: z.number()
212
+ });
213
+ var pendingIncrementalAuthSchema = z.object({
214
+ /** Unique ID for this request */
215
+ id: z.string(),
216
+ /** App ID being authorized */
217
+ appId: z.string(),
218
+ /** Tool ID that triggered the auth request */
219
+ toolId: z.string().optional(),
220
+ /** Authorization URL */
221
+ authUrl: z.string(),
222
+ /** Required scopes */
223
+ requiredScopes: z.array(z.string()).optional(),
224
+ /** Whether elicit is being used */
225
+ elicitId: z.string().optional(),
226
+ /** Timestamp when request was created */
227
+ createdAt: z.number(),
228
+ /** Expiration timestamp */
229
+ expiresAt: z.number(),
230
+ /** Status of the request */
231
+ status: z.enum(["pending", "completed", "cancelled", "expired"])
232
+ });
233
+ var authorizationVaultEntrySchema = z.object({
234
+ /** Vault ID (maps to access token jti claim) */
235
+ id: z.string(),
236
+ /** User subject identifier */
237
+ userSub: z.string(),
238
+ /** User email */
239
+ userEmail: z.string().optional(),
240
+ /** User name */
241
+ userName: z.string().optional(),
242
+ /** Client ID that created this session */
243
+ clientId: z.string(),
244
+ /** Creation timestamp */
245
+ createdAt: z.number(),
246
+ /** Last access timestamp */
247
+ lastAccessAt: z.number(),
248
+ /** App credentials (keyed by `${appId}:${providerId}`) */
249
+ appCredentials: z.record(z.string(), appCredentialSchema).default({}),
250
+ /** Consent record */
251
+ consent: vaultConsentRecordSchema.optional(),
252
+ /** Federated login record */
253
+ federated: vaultFederatedRecordSchema.optional(),
254
+ /** Pending incremental authorization requests */
255
+ pendingAuths: z.array(pendingIncrementalAuthSchema),
256
+ /** Apps that are fully authorized */
257
+ authorizedAppIds: z.array(z.string()),
258
+ /** Apps that were skipped (not yet authorized) */
259
+ skippedAppIds: z.array(z.string())
260
+ });
261
+ export {
262
+ apiKeyCredentialSchema,
263
+ appCredentialSchema,
264
+ authorizationVaultEntrySchema,
265
+ basicAuthCredentialSchema,
266
+ bearerCredentialSchema,
267
+ credentialSchema,
268
+ credentialTypeSchema,
269
+ customCredentialSchema,
270
+ mtlsCredentialSchema,
271
+ oauthCredentialSchema,
272
+ pendingIncrementalAuthSchema,
273
+ pkceOAuthCredentialSchema,
274
+ privateKeyCredentialSchema,
275
+ serviceAccountCredentialSchema,
276
+ sshKeyCredentialSchema,
277
+ vaultConsentRecordSchema,
278
+ vaultFederatedRecordSchema
279
+ };