@micacms/auth-oidc 0.4.1 → 0.5.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.
- package/dist/admission.d.ts +2 -4
- package/dist/admission.d.ts.map +1 -1
- package/dist/admission.js +2 -4
- package/dist/admission.js.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/gate.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/oidc.js.map +1 -1
- package/dist/return-to.js.map +1 -1
- package/dist/routes.js.map +1 -1
- package/dist/session.js.map +1 -1
- package/package.json +3 -3
package/dist/admission.d.ts
CHANGED
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
* perfectly valid ID token is the beginning of the question rather than the
|
|
7
7
|
* answer to it.
|
|
8
8
|
*
|
|
9
|
-
* Mica
|
|
10
|
-
* has no accounts to put in it. Admission is configuration:
|
|
9
|
+
* Mica has no accounts, so admission is configuration:
|
|
11
10
|
*
|
|
12
11
|
* MICA_ADMIT_GROUP=mica-editors a claim the provider sends
|
|
13
12
|
* MICA_ADMIT_DOMAIN=example.com every verified address there
|
|
@@ -24,8 +23,7 @@
|
|
|
24
23
|
* the provider does not take effect until their next sign-in, because the
|
|
25
24
|
* claims Mica checks are the ones it was given. Configuration changes *are*
|
|
26
25
|
* immediate — this policy is re-read on every request — and the session
|
|
27
|
-
* lifetime is the upper bound on the rest.
|
|
28
|
-
* decision in docs/decisions.md.
|
|
26
|
+
* lifetime is the upper bound on the rest. docs/decisions.md records the trade.
|
|
29
27
|
*/
|
|
30
28
|
import type { AuthConfig } from "./config.js";
|
|
31
29
|
import type { SessionIdentity } from "./session.js";
|
package/dist/admission.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../src/admission.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../src/admission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,MAAM,eAAe,GAAG;IAAE,QAAQ,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvF,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,QAAQ,EAAE,eAAe,GAAG,eAAe,CAAC;CACpD;AAsCD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,aAAa,GAAG,cAAc,GAAG,aAAa,GAAG,eAAe,CAAC,GACzF,eAAe,CAsDjB"}
|
package/dist/admission.js
CHANGED
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
* perfectly valid ID token is the beginning of the question rather than the
|
|
7
7
|
* answer to it.
|
|
8
8
|
*
|
|
9
|
-
* Mica
|
|
10
|
-
* has no accounts to put in it. Admission is configuration:
|
|
9
|
+
* Mica has no accounts, so admission is configuration:
|
|
11
10
|
*
|
|
12
11
|
* MICA_ADMIT_GROUP=mica-editors a claim the provider sends
|
|
13
12
|
* MICA_ADMIT_DOMAIN=example.com every verified address there
|
|
@@ -24,8 +23,7 @@
|
|
|
24
23
|
* the provider does not take effect until their next sign-in, because the
|
|
25
24
|
* claims Mica checks are the ones it was given. Configuration changes *are*
|
|
26
25
|
* immediate — this policy is re-read on every request — and the session
|
|
27
|
-
* lifetime is the upper bound on the rest.
|
|
28
|
-
* decision in docs/decisions.md.
|
|
26
|
+
* lifetime is the upper bound on the rest. docs/decisions.md records the trade.
|
|
29
27
|
*/
|
|
30
28
|
/**
|
|
31
29
|
* The strictest rule: the subject never changes and is never reassigned. The
|
package/dist/admission.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admission.js","sourceRoot":"","sources":["../src/admission.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"admission.js","sourceRoot":"","sources":["../src/admission.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Admission — who may edit this site.\n *\n * OpenID Connect states who a person is. It says nothing about whether that\n * person may edit this website: a provider vouches for a whole company, and a\n * perfectly valid ID token is the beginning of the question rather than the\n * answer to it.\n *\n * Mica has no accounts, so admission is configuration:\n *\n * MICA_ADMIT_GROUP=mica-editors a claim the provider sends\n * MICA_ADMIT_DOMAIN=example.com every verified address there\n * MICA_ADMIT_EMAILS=alice@gmail.com these verified addresses\n * MICA_ADMIT_SUBJECTS=https://id.example.com|a1b2c3\n *\n * The group rule is the one to grow into. Adding an editor is then a group\n * change in the identity provider — where the operator already manages\n * joiners and leavers — and Mica is not touched, not restarted, and holds no\n * copy of the list to go stale. The email list exists for a provider with no\n * groups, such as Google; the subject list for one that verifies no addresses.\n *\n * What this costs, and it is a real cost: removing somebody from a group at\n * the provider does not take effect until their next sign-in, because the\n * claims Mica checks are the ones it was given. Configuration changes *are*\n * immediate — this policy is re-read on every request — and the session\n * lifetime is the upper bound on the rest. docs/decisions.md records the trade.\n */\n\nimport type { AuthConfig } from \"./config.js\";\nimport type { SessionIdentity } from \"./session.js\";\n\nexport type AdmissionResult = { admitted: true } | { admitted: false; reason: string };\n\nexport interface AdmissionPolicy {\n /** One line for the startup log, so an operator can see what is in force. */\n readonly summary: string;\n admits(identity: SessionIdentity): AdmissionResult;\n}\n\n/**\n * The strictest rule: the subject never changes and is never reassigned. The\n * issuer is part of the key because a subject is only unique within the\n * provider that issued it.\n */\nfunction matchesSubject(\n identity: SessionIdentity,\n entries: ReadonlyArray<{ issuer: string; subject: string }>,\n): boolean {\n return entries.some(\n (entry) => entry.issuer === identity.issuer && entry.subject === identity.subject,\n );\n}\n\nfunction matchesEmail(identity: SessionIdentity, emails: readonly string[]): boolean {\n return emails.includes(identity.email.toLowerCase());\n}\n\nfunction matchesDomain(identity: SessionIdentity, domains: readonly string[]): boolean {\n const at = identity.email.lastIndexOf(\"@\");\n if (at < 0) return false;\n return domains.includes(identity.email.slice(at + 1).toLowerCase());\n}\n\n/**\n * Group names are compared case-sensitively, and a leading `/` is ignored.\n *\n * Keycloak sends group paths — `/mica-editors` — while most other providers\n * send bare names. Accepting both means an operator writes the name they see\n * in their own console, which is the only name they have.\n */\nfunction matchesGroup(identity: SessionIdentity, groups: readonly string[]): boolean {\n const held = new Set(identity.groups.map((group) => group.replace(/^\\//, \"\")));\n return groups.some((group) => held.has(group.replace(/^\\//, \"\")));\n}\n\nexport function createAdmissionPolicy(\n config: Pick<AuthConfig, \"admitGroups\" | \"admitDomains\" | \"admitEmails\" | \"admitSubjects\">,\n): AdmissionPolicy {\n const { admitGroups, admitDomains, admitEmails, admitSubjects } = config;\n\n const summary = [\n admitGroups.length > 0 ? `group=${admitGroups.join(\"|\")}` : null,\n admitDomains.length > 0 ? `domain=${admitDomains.join(\"|\")}` : null,\n admitEmails.length > 0 ? `emails=${admitEmails.length}` : null,\n admitSubjects.length > 0 ? `subjects=${admitSubjects.length}` : null,\n ]\n .filter(Boolean)\n .join(\", \");\n\n return {\n summary,\n\n admits(identity) {\n // The explicit list first: it is the escape hatch, and it has to work\n // when the group claim is missing or the address is unverified.\n if (matchesSubject(identity, admitSubjects)) return { admitted: true };\n\n if (matchesGroup(identity, admitGroups)) return { admitted: true };\n\n const byEmail = matchesEmail(identity, admitEmails);\n if (byEmail || matchesDomain(identity, admitDomains)) {\n /**\n * An email or domain rule trusts the provider to have checked the address.\n *\n * Where a provider allows self-registration, an unverified address is\n * a claim the person typed. Admitting on that would let anybody enter\n * an address they do not hold, so the rule refuses and says why — the\n * operator can turn verification on, or use a group or subject rule\n * instead.\n *\n * What remains is reassignment: an organisation that gives a former\n * editor's address to somebody new gives them this site too. Public\n * providers such as Gmail never reuse an address; the trade is\n * recorded in docs/decisions.md.\n */\n if (identity.emailVerified) return { admitted: true };\n\n return {\n admitted: false,\n reason:\n `${identity.email} is ${byEmail ? \"an admitted address\" : \"in an admitted domain\"}, ` +\n \"but the identity provider does not report the address as verified.\",\n };\n }\n\n return {\n admitted: false,\n reason: `${identity.email || identity.subject} is not admitted to this site.`,\n };\n },\n };\n}\n"]}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The auth gate's slice of the environment.\n *\n * A fragment, like the runtime's: the self-hosted app spreads `authEnv` into\n * its own schema, derives with `deriveAuth`, and passes the result here. The\n * local editor never touches any of this — these variables do not exist in\n * its configuration at all, which is a stronger statement than ignoring them.\n */\n\nimport { z } from \"zod\";\n\nimport { ConfigError, list } from \"@micacms/runtime\";\n\nexport const authEnv = {\n /**\n * OpenID Connect. Mica implements no passwords, no reset flow and no second\n * factor. It asks a provider who you are; the admission rules below decide\n * whether that person may edit this site.\n */\n MICA_OIDC_ISSUER: z.string().url().optional(),\n MICA_OIDC_CLIENT_ID: z.string().optional(),\n /** Omit for a public client using PKCE alone. */\n MICA_OIDC_CLIENT_SECRET: z.string().optional(),\n MICA_OIDC_SCOPE: z.string().default(\"openid profile email\"),\n /**\n * Which claim carries the person's groups. There is no standard one:\n * Keycloak and Entra normally send `groups`, others send `roles`, and some\n * send whatever the operator mapped. Naming it here is what keeps\n * `MICA_ADMIT_GROUP` working against any provider.\n */\n MICA_OIDC_GROUPS_CLAIM: z.string().default(\"groups\"),\n\n /**\n * Who may edit this site. Authentication says who somebody is; these say\n * whether that person gets in. At least one is required — the composition\n * refuses to start without one. Comma-separated, all four.\n */\n MICA_ADMIT_GROUP: z.string().optional(),\n MICA_ADMIT_DOMAIN: z.string().optional(),\n /** Verified addresses — the list for a provider with no groups, such as Google. */\n MICA_ADMIT_EMAILS: z.string().optional(),\n /** `issuer|subject` pairs — see admission.ts. */\n MICA_ADMIT_SUBJECTS: z.string().optional(),\n\n /** Signs session cookies. Rotating it invalidates every session. */\n SESSION_SECRET: z.string().min(32).optional(),\n /**\n * Deliberately short. Admission is configuration and is re-read on every\n * request; what cannot be immediate is a change *at the provider*, which\n * Mica only sees at the next sign-in. The session lifetime is therefore the\n * upper bound on how long a revoked editor keeps working.\n */\n SESSION_TTL_HOURS: z.coerce.number().int().positive().default(8),\n SESSION_IDLE_HOURS: z.coerce.number().int().positive().default(4),\n\n LOGIN_MAX_ATTEMPTS: z.coerce.number().int().positive().default(10),\n LOGIN_WINDOW_MS: z.coerce\n .number()\n .int()\n .positive()\n .default(15 * 60 * 1000),\n};\n\nconst authSchema = z.object(authEnv);\nexport type AuthEnv = z.infer<typeof authSchema>;\n\n/** The derived values the gate reads, on top of the parsed environment. */\nexport function deriveAuth<T extends AuthEnv & { NODE_ENV: string; MICA_PUBLIC_URL: string }>(\n env: T,\n) {\n return {\n ...env,\n /**\n * Discovery over plain HTTP, for an identity provider running on\n * localhost. Never in production, and never for a remote host.\n */\n oidcAllowInsecure:\n env.NODE_ENV !== \"production\" &&\n /^http:\\/\\/(localhost|127\\.0\\.0\\.1)(:|\\/|$)/.test(env.MICA_OIDC_ISSUER ?? \"\"),\n admitGroups: list(env.MICA_ADMIT_GROUP),\n // Lowercased: a domain is case-insensitive, and an operator who writes\n // `Example.com` means the same thing the provider spells `example.com`.\n admitDomains: list(env.MICA_ADMIT_DOMAIN).map((domain) =>\n domain.toLowerCase().replace(/^@/, \"\"),\n ),\n admitEmails: list(env.MICA_ADMIT_EMAILS).map((email) => email.toLowerCase()),\n admitSubjects: list(env.MICA_ADMIT_SUBJECTS).map((entry) => {\n const separator = entry.indexOf(\"|\");\n return {\n issuer: separator < 0 ? \"\" : entry.slice(0, separator).trim(),\n subject: separator < 0 ? entry : entry.slice(separator + 1).trim(),\n };\n }),\n // Secure cookies are not sent over plain HTTP, which would break a\n // localhost trial run.\n cookieSecure: env.MICA_PUBLIC_URL.startsWith(\"https://\"),\n };\n}\n\n/** What the gate requires of a finished configuration. */\nexport interface AuthConfig {\n MICA_PUBLIC_URL: string;\n isProduction: boolean;\n MICA_OIDC_ISSUER?: string | undefined;\n MICA_OIDC_CLIENT_ID?: string | undefined;\n MICA_OIDC_CLIENT_SECRET?: string | undefined;\n MICA_OIDC_SCOPE: string;\n MICA_OIDC_GROUPS_CLAIM: string;\n oidcAllowInsecure: boolean;\n admitGroups: string[];\n admitDomains: string[];\n admitEmails: string[];\n admitSubjects: Array<{ issuer: string; subject: string }>;\n /** Resolved by the app: mandatory in production, ephemeral in development. */\n sessionSecret: string;\n cookieSecure: boolean;\n SESSION_TTL_HOURS: number;\n SESSION_IDLE_HOURS: number;\n LOGIN_MAX_ATTEMPTS: number;\n LOGIN_WINDOW_MS: number;\n}\n\n/**\n * Domains where anybody can register an address. A domain rule naming one\n * admits the public, so it is refused; name the addresses instead.\n */\nconst PUBLIC_EMAIL_DOMAINS = new Set([\n \"gmail.com\",\n \"googlemail.com\",\n \"outlook.com\",\n \"hotmail.com\",\n \"live.com\",\n \"msn.com\",\n \"yahoo.com\",\n \"icloud.com\",\n \"me.com\",\n \"aol.com\",\n \"proton.me\",\n \"protonmail.com\",\n \"gmx.com\",\n \"gmx.net\",\n \"gmx.de\",\n \"gmx.ch\",\n \"web.de\",\n]);\n\n/**\n * The refusals that make a deployment honest before it serves a request.\n *\n * An OIDC deployment that admits every person its issuer knows is a\n * misconfiguration, not a default — see decisions.md.\n */\nexport function requireAuthConfig(config: {\n MICA_PUBLIC_URL: string;\n MICA_OIDC_ISSUER?: string | undefined;\n MICA_OIDC_CLIENT_ID?: string | undefined;\n admitGroups: string[];\n admitDomains: string[];\n admitEmails: string[];\n admitSubjects: Array<{ issuer: string; subject: string }>;\n}): void {\n const needed = ([\"MICA_OIDC_ISSUER\", \"MICA_OIDC_CLIENT_ID\"] as const).filter(\n (key) => !config[key],\n );\n\n if (needed.length > 0) {\n throw new ConfigError(\n `This deployment authenticates with OpenID Connect, so ` +\n `${needed.join(\" and \")} must be set.\\n` +\n \" Mica implements no passwords. Point it at Keycloak, Authentik,\\n\" +\n \" ZITADEL, Entra, Okta, Google — anything that speaks OIDC.\\n\" +\n ` The redirect URI to register is ${config.MICA_PUBLIC_URL}/api/auth/callback`,\n );\n }\n\n if (\n config.admitGroups.length === 0 &&\n config.admitDomains.length === 0 &&\n config.admitEmails.length === 0 &&\n config.admitSubjects.length === 0\n ) {\n throw new ConfigError(\n \"Nothing says who may edit this site.\\n\" +\n \" Authentication is not admission: your provider will happily vouch for\\n\" +\n \" everybody it knows. Set at least one of these:\\n\\n\" +\n \" MICA_ADMIT_GROUP=mica-editors a claim your provider sends\\n\" +\n \" MICA_ADMIT_DOMAIN=example.com every verified address there\\n\" +\n \" MICA_ADMIT_EMAILS=alice@gmail.com these verified addresses\\n\" +\n \" MICA_ADMIT_SUBJECTS=https://id.example.com|a1b2c3\\n\\n\" +\n \" The group rule is the one to grow into: adding an editor is then a\\n\" +\n \" change in the identity provider, and Mica is not touched.\",\n );\n }\n\n const open = config.admitDomains.filter((domain) => PUBLIC_EMAIL_DOMAINS.has(domain));\n if (open.length > 0) {\n throw new ConfigError(\n `MICA_ADMIT_DOMAIN names ${open.join(\", \")}, where anybody can register an address.\\n` +\n \" That rule would let the public edit this site. Name the people instead:\\n\" +\n \" MICA_ADMIT_EMAILS=alice@gmail.com,bob@gmail.com\",\n );\n }\n\n const malformed = config.admitEmails.filter((email) => !/^[^@\\s]+@[^@\\s]+$/.test(email));\n if (malformed.length > 0) {\n throw new ConfigError(\n `MICA_ADMIT_EMAILS entries are email addresses, and these are not: ${malformed.join(\", \")}`,\n );\n }\n\n const wrong = config.admitSubjects.filter((entry) => !entry.issuer || !entry.subject);\n if (wrong.length > 0) {\n throw new ConfigError(\n \"MICA_ADMIT_SUBJECTS entries are `issuer|subject` pairs, and one is not:\\n\" +\n ` ${wrong.map((entry) => entry.subject || \"(empty)\").join(\", \")}\\n\\n` +\n \" The issuer is part of the key because a subject is only unique within\\n\" +\n \" the provider that issued it. To admit an address, use MICA_ADMIT_EMAILS.\\n\" +\n ` MICA_ADMIT_SUBJECTS=${config.MICA_OIDC_ISSUER ?? \"https://id.example.com\"}|a1b2c3`,\n );\n }\n}\n"]}
|
package/dist/gate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The gate: what stands between a request and the admin API.\n *\n * Two layers, in order. `requireAccess` turns a session cookie into an\n * `AccessContext` — or a 401 — re-checking admission on every request so a\n * configuration change is immediate, and re-issuing the cookie while the\n * session is in use. `csrfProtection` is the double-submit\n * token over the Origin check the runtime already applies: cross-origin\n * JavaScript can neither read the cookie nor set the header.\n */\n\nimport { getCookie, setCookie } from \"hono/cookie\";\nimport type { Context, MiddlewareHandler } from \"hono\";\n\nimport { ApiError, type Env } from \"@micacms/runtime\";\n\nimport type { AdmissionPolicy } from \"./admission.js\";\nimport {\n CSRF_HEADER,\n safeEqual,\n type SessionRecord,\n type SessionService,\n} from \"./session.js\";\n\n/**\n * The session behind the current request. Auth's own context variable —\n * the runtime knows only the `access` it derives from it.\n */\nconst SESSION_VARIABLE = \"authSession\";\n\nexport function sessionOf(c: Context<Env>): SessionRecord {\n // Set by requireAccess, which runs in front of everything that calls this.\n return c.get(SESSION_VARIABLE as never) as SessionRecord;\n}\n\nexport interface GateDeps {\n sessions: SessionService;\n admission: AdmissionPolicy;\n}\n\n/**\n * Rejects the request unless there is a live session whose person is still\n * admitted.\n *\n * Admission is re-read on every request, not decided once at sign-in. That is\n * what makes a configuration change immediate: an operator who takes somebody\n * out of `MICA_ADMIT_SUBJECTS` and restarts has removed them. What it cannot\n * make immediate is a group removal at the provider — the claims here are the\n * ones the provider sent, and Mica learns better at the next sign-in.\n */\nexport function requireAccess(deps: GateDeps): MiddlewareHandler<Env> {\n return async (c, next) => {\n let session = deps.sessions.resolve(getCookie(c, deps.sessions.names.session));\n\n if (!session) {\n throw new ApiError(\"unauthenticated\", \"Your session has expired. Please sign in again.\");\n }\n\n const { identity } = session;\n\n const verdict = deps.admission.admits(identity);\n if (!verdict.admitted) {\n c.get(\"logger\").warn(\"Session no longer admitted\", {\n subject: identity.subject,\n reason: verdict.reason,\n });\n throw new ApiError(\"forbidden\", \"You no longer have access to this site.\");\n }\n\n const refreshed = deps.sessions.refresh(session);\n if (refreshed) session = refreshed.record;\n\n c.set(SESSION_VARIABLE as never, session as never);\n c.set(\"access\", {\n identity: { subject: identity.subject, email: identity.email, name: identity.name },\n });\n await next();\n\n // After the handler, so the cookie lands on whatever response it built.\n if (refreshed) {\n setCookie(c, deps.sessions.names.session, refreshed.cookie, deps.sessions.sessionCookieOptions());\n }\n };\n}\n\nconst SAFE_METHODS = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\n\n/**\n * Second CSRF layer: double-submit token. The session's token is issued in a\n * cookie the SPA can read and must be echoed in a header.\n *\n * Runs after `requireAccess`, and complements the session cookie's\n * `SameSite=Lax`, which already blocks the classic cross-site form post.\n */\nexport function csrfProtection(deps: GateDeps): MiddlewareHandler<Env> {\n return async (c, next) => {\n if (SAFE_METHODS.has(c.req.method)) {\n await next();\n return;\n }\n\n const session = sessionOf(c);\n const header = c.req.header(CSRF_HEADER);\n const cookie = getCookie(c, deps.sessions.names.csrf);\n\n if (!header || !cookie || !safeEqual(header, cookie) || !safeEqual(header, session.csrfToken)) {\n throw new ApiError(\"forbidden\", \"Invalid or missing CSRF token. Reload the page and retry.\");\n }\n\n await next();\n };\n}\n"]}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,iBAAiB,EAAoB,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,qBAAqB,EAAwB,MAAM,gBAAgB,CAAC;AAE7E,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAoB,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAuB,MAAM,cAAc,CAAC;AAgBzE,MAAM,UAAU,cAAc,CAAC,IAAkB;IAC/C,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAEhC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,iBAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,iBAAiB,CAAC;QACrC,KAAK,EAAE,MAAM,CAAC,kBAAkB;QAChC,QAAQ,EAAE,MAAM,CAAC,eAAe;KACjC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAErC,OAAO;QACL,OAAO,EAAE;YACP,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;YACvE,IAAI,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;SAClD;QACD,QAAQ;QACR,SAAS;QACT,IAAI;QACJ,YAAY;KACb,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,qBAAqB,EAA8C,MAAM,gBAAgB,CAAC;AACnG,OAAO,EACL,OAAO,EACP,UAAU,EACV,iBAAiB,GAGlB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAoB,MAAM,WAAW,CAAC;AAChE,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,cAAc,GAIf,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,iBAAiB,EAAoB,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,qBAAqB,EAAwB,MAAM,gBAAgB,CAAC;AAE7E,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAoB,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAuB,MAAM,cAAc,CAAC;AAgBzE,MAAM,UAAU,cAAc,CAAC,IAAkB;IAC/C,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAEhC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,iBAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,iBAAiB,CAAC;QACrC,KAAK,EAAE,MAAM,CAAC,kBAAkB;QAChC,QAAQ,EAAE,MAAM,CAAC,eAAe;KACjC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAErC,OAAO;QACL,OAAO,EAAE;YACP,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;YACvE,IAAI,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;SAClD;QACD,QAAQ;QACR,SAAS;QACT,IAAI;QACJ,YAAY;KACb,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,qBAAqB,EAA8C,MAAM,gBAAgB,CAAC;AACnG,OAAO,EACL,OAAO,EACP,UAAU,EACV,iBAAiB,GAGlB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAoB,MAAM,WAAW,CAAC;AAChE,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,cAAc,GAIf,MAAM,cAAc,CAAC","sourcesContent":["/**\n * @micacms/auth-oidc — the server-only OIDC gate around @micacms/runtime.\n *\n * One factory: hand it the finished configuration and a logger, and it\n * returns the `AuthSurface` the runtime mounts — sign-in\n * routes at `/api/auth`, and the session-plus-CSRF gate in front of the admin\n * API — together with the services the composing app reports on.\n *\n * This package is a dependency of `@micacms/self-hosted` and of nothing else.\n * The local editor must never gain a path to it: that absence is the product\n * boundary that keeps `npx @micacms/editor` free of authentication code.\n */\n\nimport type { AuthSurface, Logger } from \"@micacms/runtime\";\nimport { createRateLimiter, type RateLimiter } from \"@micacms/runtime\";\n\nimport { createAdmissionPolicy, type AdmissionPolicy } from \"./admission.js\";\nimport type { AuthConfig } from \"./config.js\";\nimport { csrfProtection, requireAccess } from \"./gate.js\";\nimport { createOidcService, type OidcService } from \"./oidc.js\";\nimport { authRoutes } from \"./routes.js\";\nimport { createSessionService, type SessionService } from \"./session.js\";\n\nexport interface OidcAuthDeps {\n config: AuthConfig;\n logger: Logger;\n}\n\nexport interface OidcAuth {\n /** What `createApp` mounts: routes at /api/auth, the gate before /api/admin. */\n surface: AuthSurface;\n sessions: SessionService;\n admission: AdmissionPolicy;\n oidc: OidcService;\n loginLimiter: RateLimiter;\n}\n\nexport function createOidcAuth(deps: OidcAuthDeps): OidcAuth {\n const { config, logger } = deps;\n\n const sessions = createSessionService(config);\n const admission = createAdmissionPolicy(config);\n const oidc = createOidcService({ config, logger });\n const loginLimiter = createRateLimiter({\n limit: config.LOGIN_MAX_ATTEMPTS,\n windowMs: config.LOGIN_WINDOW_MS,\n });\n\n const gate = { sessions, admission };\n\n return {\n surface: {\n routes: authRoutes({ config, sessions, oidc, admission, loginLimiter }),\n gate: [requireAccess(gate), csrfProtection(gate)],\n },\n sessions,\n admission,\n oidc,\n loginLimiter,\n };\n}\n\nexport { createAdmissionPolicy, type AdmissionPolicy, type AdmissionResult } from \"./admission.js\";\nexport {\n authEnv,\n deriveAuth,\n requireAuthConfig,\n type AuthConfig,\n type AuthEnv,\n} from \"./config.js\";\nexport { csrfProtection, requireAccess, sessionOf } from \"./gate.js\";\nexport { createOidcService, type OidcService } from \"./oidc.js\";\nexport {\n cookieNames,\n createSessionService,\n CSRF_COOKIE,\n CSRF_HEADER,\n SESSION_COOKIE,\n type SessionIdentity,\n type SessionRecord,\n type SessionService,\n} from \"./session.js\";\n"]}
|
package/dist/oidc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oidc.js","sourceRoot":"","sources":["../src/oidc.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"oidc.js","sourceRoot":"","sources":["../src/oidc.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * OpenID Connect.\n *\n * Mica does not authenticate anybody. It asks a provider who you are, and\n * records the answer. Hashing, reset flows, MFA, passkeys and breach response\n * all belong to the identity provider, and none of them are Mica's to get\n * wrong.\n *\n * What is Mica's is the small part here: run the authorization code flow\n * correctly and report what the provider said. Whether that person may edit\n * this site is `services/admission.ts`, and deliberately not a table.\n *\n * Three checks carry the security of the flow, and all three are enforced\n * rather than assumed:\n *\n * - **PKCE** binds the authorization code to this browser, so a code\n * intercepted in a redirect is useless to anyone else.\n * - **state** binds the callback to a request Mica actually started, which\n * is what stops an attacker feeding a victim their own login.\n * - **nonce** binds the ID token to that same request, so a token replayed\n * from elsewhere does not validate.\n *\n * They are carried in a short-lived signed cookie rather than in the database:\n * the transaction lasts one redirect, and a table of them would be a table of\n * garbage to collect.\n */\n\nimport { createHmac, hkdfSync, randomBytes, timingSafeEqual } from \"node:crypto\";\n\nimport * as client from \"openid-client\";\n\nimport { ApiError, type Logger } from \"@micacms/runtime\";\n\nimport type { AuthConfig } from \"./config.js\";\n\n/**\n * How long a sign-in may take.\n *\n * Long enough to enter a second factor and read an email; short enough that an\n * abandoned transaction cookie is not a lasting liability.\n */\nconst TRANSACTION_TTL_MS = 15 * 60 * 1000;\n\nexport interface OidcTransaction {\n state: string;\n nonce: string;\n verifier: string;\n /** Where to send the browser once the session exists. */\n returnTo: string;\n expiresAt: number;\n}\n\n/** What the provider told us about the person signing in. */\nexport interface OidcClaims {\n issuer: string;\n subject: string;\n email: string;\n /** The provider's `email_verified`. Absent counts as false, never as true. */\n emailVerified: boolean;\n name: string;\n /** The configured groups claim, or empty when the provider sends none. */\n groups: string[];\n}\n\n/* ------------------------------------------------------------------ *\n * The transaction cookie\n * ------------------------------------------------------------------ */\n\n// Its own key, derived like the session's: one secret, never used directly for two purposes (#91).\nconst transactionKey = (secret: string): Buffer =>\n Buffer.from(hkdfSync(\"sha256\", secret, \"\", \"mica oidc transaction v1\", 32));\n\nfunction sign(value: string, secret: string): string {\n return createHmac(\"sha256\", transactionKey(secret)).update(value).digest(\"base64url\");\n}\n\nfunction safeEqual(a: string, b: string): boolean {\n const left = Buffer.from(a);\n const right = Buffer.from(b);\n return left.length === right.length && timingSafeEqual(left, right);\n}\n\nexport function sealTransaction(transaction: OidcTransaction, secret: string): string {\n const payload = Buffer.from(JSON.stringify(transaction)).toString(\"base64url\");\n return `${payload}.${sign(payload, secret)}`;\n}\n\nexport function openTransaction(cookie: string, secret: string): OidcTransaction | null {\n const separator = cookie.lastIndexOf(\".\");\n if (separator < 1) return null;\n\n const payload = cookie.slice(0, separator);\n const signature = cookie.slice(separator + 1);\n\n if (!safeEqual(signature, sign(payload, secret))) return null;\n\n try {\n const transaction = JSON.parse(\n Buffer.from(payload, \"base64url\").toString(\"utf8\"),\n ) as OidcTransaction;\n\n return transaction.expiresAt > Date.now() ? transaction : null;\n } catch {\n return null;\n }\n}\n\n/**\n * The address and its `email_verified` flag, always from the same answer, so\n * that a flag cannot vouch for an address it was not sent with (#91). Userinfo\n * fills in an address the ID token lacks, or confirms the token's own address.\n */\nexport function emailFrom(\n claims: Record<string, unknown>,\n info?: Record<string, unknown>,\n): { email: string; emailVerified: boolean } {\n const tokenEmail = typeof claims[\"email\"] === \"string\" ? claims[\"email\"] : \"\";\n const infoEmail = typeof info?.[\"email\"] === \"string\" ? info[\"email\"] : \"\";\n const infoVerified = info?.[\"email_verified\"] === true;\n\n if (tokenEmail) {\n const confirmed = infoEmail === tokenEmail && infoVerified;\n return { email: tokenEmail, emailVerified: claims[\"email_verified\"] === true || confirmed };\n }\n return { email: infoEmail, emailVerified: Boolean(infoEmail) && infoVerified };\n}\n\n/* ------------------------------------------------------------------ *\n * The service\n * ------------------------------------------------------------------ */\n\nexport interface OidcServiceDeps {\n config: AuthConfig;\n logger: Logger;\n}\n\nexport function createOidcService(deps: OidcServiceDeps) {\n const { config, logger } = deps;\n\n const redirectUri = new URL(\"/api/auth/callback\", config.MICA_PUBLIC_URL).toString();\n\n /**\n * Discovery, done once and remembered.\n *\n * Lazy rather than at startup: an identity provider that is briefly\n * unreachable should delay the first sign-in, not stop Mica from booting and\n * taking its health check down with it.\n */\n let discovered: Promise<client.Configuration> | null = null;\n\n function configuration(): Promise<client.Configuration> {\n discovered ??= client\n .discovery(\n new URL(config.MICA_OIDC_ISSUER!),\n config.MICA_OIDC_CLIENT_ID!,\n config.MICA_OIDC_CLIENT_SECRET,\n undefined,\n // Only ever for a provider on localhost, and only outside production —\n // the config layer refuses the combination anywhere else.\n config.oidcAllowInsecure ? { execute: [client.allowInsecureRequests] } : undefined,\n )\n .catch((error: unknown) => {\n // Forget the failure so the next attempt retries rather than caching a\n // rejected promise for the life of the process.\n discovered = null;\n logger.error(\"OIDC discovery failed\", {\n issuer: config.MICA_OIDC_ISSUER,\n error: String(error),\n });\n throw new ApiError(\n \"service_unavailable\",\n \"The identity provider could not be reached. Try again shortly.\",\n );\n });\n\n return discovered;\n }\n\n return {\n /** Where to send a browser to sign in, plus the transaction to remember. */\n async begin(returnTo: string): Promise<{ url: string; transaction: OidcTransaction }> {\n const as = await configuration();\n\n const verifier = client.randomPKCECodeVerifier();\n const transaction: OidcTransaction = {\n state: client.randomState(),\n nonce: client.randomNonce(),\n verifier,\n returnTo,\n expiresAt: Date.now() + TRANSACTION_TTL_MS,\n };\n\n const url = client.buildAuthorizationUrl(as, {\n redirect_uri: redirectUri,\n scope: config.MICA_OIDC_SCOPE,\n state: transaction.state,\n nonce: transaction.nonce,\n code_challenge: await client.calculatePKCECodeChallenge(verifier),\n code_challenge_method: \"S256\",\n });\n\n return { url: url.toString(), transaction };\n },\n\n /**\n * Completes the flow and returns who signed in.\n *\n * `authorizationCodeGrant` verifies the ID token signature, the issuer, the\n * audience, the expiry, the nonce and the PKCE verifier. Doing any of that\n * by hand here would be reimplementing the part of this that is genuinely\n * hard to get right.\n */\n async complete(currentUrl: URL, transaction: OidcTransaction): Promise<OidcClaims> {\n const as = await configuration();\n\n let tokens: client.TokenEndpointResponse & client.TokenEndpointResponseHelpers;\n try {\n tokens = await client.authorizationCodeGrant(as, currentUrl, {\n pkceCodeVerifier: transaction.verifier,\n expectedState: transaction.state,\n expectedNonce: transaction.nonce,\n });\n } catch (error) {\n logger.warn(\"OIDC callback rejected\", { error: String(error) });\n throw new ApiError(\"unauthenticated\", \"Sign-in could not be completed. Please try again.\");\n }\n\n const claims = tokens.claims();\n if (!claims?.sub) {\n throw new ApiError(\"unauthenticated\", \"The identity provider returned no subject.\");\n }\n\n // Not every provider puts email, name and groups in the ID token; some\n // keep them at the userinfo endpoint, and some only release groups\n // there. Ask only when something is missing.\n const groupsClaim = config.MICA_OIDC_GROUPS_CLAIM;\n\n let { email, emailVerified } = emailFrom(claims);\n let name = typeof claims[\"name\"] === \"string\" ? claims[\"name\"] : \"\";\n let groups = readGroups(claims[groupsClaim]);\n\n if (!email || !emailVerified || !name || groups.length === 0) {\n try {\n const info = await client.fetchUserInfo(as, tokens.access_token, claims.sub);\n ({ email, emailVerified } = emailFrom(claims, info));\n name ||= typeof info.name === \"string\" ? info.name : \"\";\n if (groups.length === 0) groups = readGroups(info[groupsClaim]);\n } catch (error) {\n logger.debug(\"OIDC userinfo unavailable\", { error: String(error) });\n }\n }\n\n if (!email) {\n // Mica names people by email — it is who the commits are from. An\n // identity without one cannot be shown to anybody, so it is refused\n // rather than displayed as blank.\n throw new ApiError(\n \"unauthenticated\",\n \"The identity provider did not release an email address. \" +\n \"Grant Mica the `email` scope.\",\n );\n }\n\n return {\n issuer: String(claims.iss),\n subject: String(claims.sub),\n email,\n emailVerified,\n name: name || email,\n groups,\n };\n },\n\n /**\n * Where to send the browser to end the provider's session too.\n *\n * Null when the provider does not advertise the endpoint: signing out of\n * Mica always works, and signing out of the IdP is a bonus that not every\n * deployment can offer.\n */\n async endSessionUrl(): Promise<string | null> {\n try {\n const as = await configuration();\n return client\n .buildEndSessionUrl(as, {\n post_logout_redirect_uri: new URL(\"/admin/\", config.MICA_PUBLIC_URL).toString(),\n })\n .toString();\n } catch {\n return null;\n }\n },\n };\n}\n\nexport type OidcService = ReturnType<typeof createOidcService>;\n\n/**\n * A groups claim, from a provider that may not send one and is under no\n * obligation to send it as an array.\n *\n * Keycloak sends a list of paths, Entra a list of ids, some deployments a\n * single string, and a misconfigured mapper sends an object. Everything that\n * is not a string in a list is dropped rather than coerced, because a group\n * name Mica invented would be a group name that could match a rule.\n */\nfunction readGroups(value: unknown): string[] {\n if (typeof value === \"string\") return value.split(/[,\\s]+/).filter(Boolean);\n if (!Array.isArray(value)) return [];\n return value.filter((entry): entry is string => typeof entry === \"string\");\n}\n\n/** A random return path token, for the local mode that has no provider. */\nexport const randomToken = (): string => randomBytes(32).toString(\"base64url\");\n"]}
|
package/dist/return-to.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"return-to.js","sourceRoot":"","sources":["../src/return-to.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAuB,EAAE,SAAiB;IACrE,MAAM,QAAQ,GAAG,SAAS,CAAC;IAC3B,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IAElD,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IAC9D,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IACtF,OAAO,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;AACnD,CAAC"}
|
|
1
|
+
{"version":3,"file":"return-to.js","sourceRoot":"","sources":["../src/return-to.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAuB,EAAE,SAAiB;IACrE,MAAM,QAAQ,GAAG,SAAS,CAAC;IAC3B,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IAElD,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IAC9D,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IACtF,OAAO,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;AACnD,CAAC","sourcesContent":["/**\n * Where the browser goes after sign-in: a page of this editor, or the start page.\n *\n * Parsed the way a browser parses a `Location`, so that `/\\evil.example`, a\n * tab or a line break cannot turn a path into another host (#87).\n */\nexport function safeReturnTo(raw: string | undefined, publicUrl: string): string {\n const fallback = \"/admin/\";\n if (!raw || !raw.startsWith(\"/\")) return fallback;\n\n let url: URL;\n try {\n url = new URL(raw, publicUrl);\n } catch {\n return fallback;\n }\n\n if (url.origin !== new URL(publicUrl).origin) return fallback;\n if (url.pathname !== \"/admin\" && !url.pathname.startsWith(\"/admin/\")) return fallback;\n return `${url.pathname}${url.search}${url.hash}`;\n}\n"]}
|
package/dist/routes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Authentication routes.\n *\n * The authorization code flow, and nothing else. There is no login form here,\n * no password check and no reset: the browser is sent to an identity provider,\n * comes back with a code, and Mica exchanges it for a statement about who the\n * person is.\n *\n * What Mica still decides is whether that person may edit *this site*. A valid\n * token from a correctly configured provider proves an identity and nothing\n * more; `admission.ts` is the gate, and an unknown person hits it.\n */\n\nimport { Hono } from \"hono\";\nimport { deleteCookie, getCookie, setCookie } from \"hono/cookie\";\n\nimport { ApiError, clientIp, type Env, type RateLimiter } from \"@micacms/runtime\";\n\nimport type { AdmissionPolicy } from \"./admission.js\";\nimport type { AuthConfig } from \"./config.js\";\nimport { requireAccess, sessionOf, type GateDeps } from \"./gate.js\";\nimport { safeReturnTo } from \"./return-to.js\";\nimport {\n establishSession,\n type SessionIdentity,\n type SessionService,\n} from \"./session.js\";\nimport {\n openTransaction,\n sealTransaction,\n type OidcClaims,\n type OidcService,\n} from \"./oidc.js\";\n\nconst identityOf = (claims: OidcClaims): SessionIdentity => ({\n issuer: claims.issuer,\n subject: claims.subject,\n email: claims.email,\n emailVerified: claims.emailVerified,\n name: claims.name,\n groups: claims.groups,\n});\n\n/** Why a sign-in came back to the login view. The SPA has the words for each. */\nexport type SignInRefusal = \"rate_limited\" | \"expired\" | \"failed\" | \"not_admitted\" | \"too_large\";\n\nexport interface AuthRoutesDeps {\n config: AuthConfig;\n sessions: SessionService;\n oidc: OidcService;\n admission: AdmissionPolicy;\n loginLimiter: RateLimiter;\n}\n\nexport function authRoutes(deps: AuthRoutesDeps): Hono<Env> {\n const app = new Hono<Env>();\n const { config, sessions, oidc, admission } = deps;\n const gate: GateDeps = deps;\n\n /**\n * What the sign-in screen needs to know before it draws anything.\n *\n * Public: it reveals only that this deployment authenticates and which\n * provider it uses, which the redirect would reveal a moment later anyway.\n */\n app.get(\"/config\", (c) =>\n c.json({\n authRequired: true,\n provider: config.MICA_OIDC_ISSUER ? new URL(config.MICA_OIDC_ISSUER).hostname : null,\n }),\n );\n\n /** Starts the flow. A redirect, not a form post. */\n app.get(\"/login\", async (c) => {\n const returnTo = safeReturnTo(c.req.query(\"returnTo\"), config.MICA_PUBLIC_URL);\n\n // Rate limited on the way out and on the way back (in /callback): starting a\n // flow is cheap for a client and costs Mica a discovery request.\n const limit = deps.loginLimiter.check(`oidc:${clientIp(c)}`);\n if (!limit.allowed) {\n throw new ApiError(\n \"rate_limited\",\n `Too many sign-in attempts. Try again in ${Math.ceil(limit.retryAfter / 60)} minutes.`,\n { headers: { \"retry-after\": String(limit.retryAfter) } },\n );\n }\n\n const { url, transaction } = await oidc.begin(returnTo);\n\n setCookie(c, sessions.names.transaction, sealTransaction(transaction, config.sessionSecret), {\n path: \"/api/auth\",\n httpOnly: true,\n secure: config.cookieSecure,\n // Lax, not Strict: the provider redirects the browser back here from\n // another origin, and Strict would withhold the cookie exactly then.\n sameSite: \"Lax\",\n maxAge: 15 * 60,\n });\n\n return c.redirect(url);\n });\n\n /**\n * Where the provider sends the browser back.\n *\n * A browser is following a redirect here, not making an XHR, so a failure\n * must not be a JSON error envelope — that would put a wall of braces on the\n * screen. Everything that can go wrong goes back to the sign-in page with a\n * message the person can act on.\n */\n app.get(\"/callback\", async (c) => {\n const logger = c.get(\"logger\");\n\n // A code, not a sentence: the URL lands in browser history and proxy logs,\n // so it must not carry the person's address (#150). The login view words it.\n const refuse = (code: SignInRefusal) => c.redirect(`/admin/login?error=${code}`);\n\n // A replayed transaction cookie would call the token endpoint each time.\n // Its own key, so that one sign-in does not count twice against the start.\n if (!deps.loginLimiter.check(`oidc-callback:${clientIp(c)}`).allowed) {\n return refuse(\"rate_limited\");\n }\n\n const sealed = getCookie(c, sessions.names.transaction);\n deleteCookie(c, sessions.names.transaction, { path: \"/api/auth\", secure: config.cookieSecure });\n\n const transaction = sealed ? openTransaction(sealed, config.sessionSecret) : null;\n if (!transaction) {\n // Expired, tampered with, or a callback nobody asked for.\n return refuse(\"expired\");\n }\n\n let claims: OidcClaims;\n try {\n claims = await oidc.complete(new URL(c.req.url), transaction);\n } catch (error) {\n logger.warn(\"Sign-in could not be completed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return refuse(\"failed\");\n }\n\n const identity = identityOf(claims);\n\n /**\n * Authentication succeeded; admission is a separate question.\n *\n * A provider may vouch for an entire company. The admission rules are what\n * say this particular person may edit this particular site, and their\n * refusal is the expected answer for everybody who was not meant to be\n * here — so it is a plain message, not an error.\n */\n const verdict = admission.admits(identity);\n if (!verdict.admitted) {\n logger.warn(\"Authenticated but not admitted\", {\n subject: identity.subject,\n reason: verdict.reason,\n });\n return refuse(\"not_admitted\");\n }\n\n try {\n establishSession(c, sessions, identity);\n } catch (error) {\n logger.error(\"Could not start a session\", { subject: identity.subject, error });\n return refuse(\"too_large\");\n }\n logger.info(\"Signed in\", { subject: identity.subject, issuer: identity.issuer });\n\n return c.redirect(transaction.returnTo);\n });\n\n // There is no server-side session to end; clearing the cookies is sign-out.\n app.post(\"/logout\", async (c) => {\n deleteCookie(c, sessions.names.session, sessions.clearedCookieOptions());\n deleteCookie(c, sessions.names.csrf, sessions.clearedCookieOptions());\n\n // Offered, not followed: ending the provider's session is the provider's\n // decision to make, and the SPA sends the browser there if it is there.\n return c.json({ ok: true, endSession: await oidc.endSessionUrl() });\n });\n\n /** The session this request is in, and who it belongs to. */\n app.get(\"/me\", requireAccess(gate), (c) => {\n const session = sessionOf(c);\n const { identity } = c.get(\"access\");\n\n return c.json({\n identity,\n csrfToken: session.csrfToken,\n expiresAt: session.expiresAt,\n });\n });\n\n return app;\n}\n"]}
|
package/dist/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Session management.\n *\n * The session is the cookie: who the provider said this is, a CSRF token and\n * an expiry, encrypted with a key derived from SESSION_SECRET. There is no\n * session table, so Mica stores nothing about people at all.\n *\n * - AES-256-GCM, so the cookie can be neither read nor altered. Encrypted and\n * not only signed, because it carries an email address and groups.\n * - A fresh random IV per cookie, and a new cookie at every sign-in, so a\n * client-supplied value is never adopted (session fixation).\n * - The idle window slides: an active session is re-issued every few\n * minutes with a later expiry, capped by the absolute lifetime.\n *\n * What this gives up is server-side revocation of one cookie. Sign-out clears\n * it in the browser; a copy taken before then stays valid until it expires.\n * Rotating SESSION_SECRET ends every session at once. The admission rules are\n * still re-read on every request — see gate.ts and docs/decisions.md.\n */\n\nimport { createCipheriv, createDecipheriv, hkdfSync, randomBytes, timingSafeEqual } from \"node:crypto\";\n\nimport type { Context } from \"hono\";\nimport { setCookie } from \"hono/cookie\";\n\nimport { randomToken, type Env } from \"@micacms/runtime\";\n\nimport type { AuthConfig } from \"./config.js\";\n\nexport const SESSION_COOKIE = \"mica_session\";\nexport const CSRF_COOKIE = \"mica_csrf\";\nexport const CSRF_HEADER = \"x-csrf-token\";\nexport const TRANSACTION_COOKIE = \"mica_oidc\";\n\nexport interface CookieNames {\n session: string;\n csrf: string;\n transaction: string;\n}\n\n/**\n * With https, the names carry a prefix the browser enforces: `__Host-` means\n * Secure, path `/` and no Domain, so a sibling subdomain cannot plant or\n * overwrite the cookie. The transaction cookie is scoped to `/api/auth`, so it\n * can only be `__Secure-`. Over plain HTTP the cookies are not Secure, and a\n * browser would refuse a prefixed name.\n */\nexport function cookieNames(secure: boolean): CookieNames {\n return secure\n ? {\n session: `__Host-${SESSION_COOKIE}`,\n csrf: `__Host-${CSRF_COOKIE}`,\n transaction: `__Secure-${TRANSACTION_COOKIE}`,\n }\n : { session: SESSION_COOKIE, csrf: CSRF_COOKIE, transaction: TRANSACTION_COOKIE };\n}\n\n/** How often an active session is re-issued with a later idle expiry. */\nconst REFRESH_INTERVAL_MS = 5 * 60 * 1000;\n\n/** Browsers drop cookies over 4096 bytes; refuse rather than sign in to nothing. */\nconst MAX_COOKIE_BYTES = 4000;\n\nconst IV_BYTES = 12;\nconst TAG_BYTES = 16;\n\n/** What the identity provider stated about the person holding this session. */\nexport interface SessionIdentity {\n issuer: string;\n /** Opaque and stable at that issuer. */\n subject: string;\n email: string;\n /** The provider's own `email_verified`. Absent counts as false. */\n emailVerified: boolean;\n name: string;\n /** The groups claim, reduced at sign-in to the groups the rules name. */\n groups: string[];\n}\n\nexport interface SessionRecord {\n identity: SessionIdentity;\n csrfToken: string;\n createdAt: string;\n /** When the session was last issued; drives the sliding idle window. */\n refreshedAt: string;\n expiresAt: string;\n}\n\nexport interface SessionService {\n /** The cookie names, which depend on whether the cookies are Secure. */\n readonly names: CookieNames;\n /** Seals a new session. Throws when the identity cannot fit in a cookie. */\n create(identity: SessionIdentity): { record: SessionRecord; cookie: string };\n /** The live session in a cookie, or null for a missing, forged or expired one. */\n resolve(cookieValue: string | undefined): SessionRecord | null;\n /** A later-expiring copy of an active session, or null while it is fresh. */\n refresh(record: SessionRecord): { record: SessionRecord; cookie: string } | null;\n sessionCookieOptions(): CookieOptions;\n csrfCookieOptions(): CookieOptions;\n clearedCookieOptions(): CookieOptions;\n}\n\nexport interface CookieOptions {\n path: string;\n httpOnly: boolean;\n secure: boolean;\n sameSite: \"Lax\" | \"Strict\" | \"None\";\n maxAge: number;\n}\n\n/** Constant-time string comparison that tolerates differing lengths. */\nexport function safeEqual(a: string, b: string): boolean {\n const left = Buffer.from(a);\n const right = Buffer.from(b);\n if (left.length !== right.length) {\n // Still compare, so the branch does not leak the length difference.\n timingSafeEqual(left, left);\n return false;\n }\n return timingSafeEqual(left, right);\n}\n\n/**\n * Keycloak sends `/mica-editors` where the rule says `mica-editors`; both\n * spellings are the same group — see admission.ts.\n */\nconst groupName = (group: string): string => group.replace(/^\\//, \"\");\n\n/** Defensive read of a decrypted payload: it was written by us, but checked anyway. */\nfunction parseRecord(json: string): SessionRecord | null {\n try {\n const value = JSON.parse(json) as Partial<SessionRecord>;\n const identity = value.identity;\n if (\n !identity ||\n typeof identity.issuer !== \"string\" ||\n typeof identity.subject !== \"string\" ||\n typeof value.csrfToken !== \"string\" ||\n typeof value.createdAt !== \"string\" ||\n typeof value.refreshedAt !== \"string\" ||\n typeof value.expiresAt !== \"string\"\n ) {\n return null;\n }\n return {\n identity: {\n issuer: identity.issuer,\n subject: identity.subject,\n email: typeof identity.email === \"string\" ? identity.email : \"\",\n emailVerified: identity.emailVerified === true,\n name: typeof identity.name === \"string\" ? identity.name : \"\",\n groups: Array.isArray(identity.groups)\n ? identity.groups.filter((group): group is string => typeof group === \"string\")\n : [],\n },\n csrfToken: value.csrfToken,\n createdAt: value.createdAt,\n refreshedAt: value.refreshedAt,\n expiresAt: value.expiresAt,\n };\n } catch {\n return null;\n }\n}\n\nexport function createSessionService(config: AuthConfig): SessionService {\n const ttlMs = config.SESSION_TTL_HOURS * 3600_000;\n const idleMs = config.SESSION_IDLE_HOURS * 3600_000;\n\n const key = Buffer.from(\n hkdfSync(\"sha256\", config.sessionSecret, \"\", \"mica session cookie v1\", 32),\n );\n\n // Only the groups a rule names are kept: an Entra token can carry hundreds,\n // and a cookie holds 4 KB. A group added to the rules later counts from the\n // next sign-in.\n const admitted = new Set(config.admitGroups.map(groupName));\n\n /** Expiry is the earlier of the idle window and the absolute lifetime. */\n const nextExpiry = (createdAt: number, now: number): string =>\n new Date(Math.min(now + idleMs, createdAt + ttlMs)).toISOString();\n\n const seal = (record: SessionRecord): string => {\n const iv = randomBytes(IV_BYTES);\n const cipher = createCipheriv(\"aes-256-gcm\", key, iv);\n const body = Buffer.concat([cipher.update(JSON.stringify(record), \"utf8\"), cipher.final()]);\n const cookie = Buffer.concat([iv, body, cipher.getAuthTag()]).toString(\"base64url\");\n\n if (cookie.length > MAX_COOKIE_BYTES) {\n throw new Error(\"The session does not fit in a cookie; the identity is too large.\");\n }\n return cookie;\n };\n\n const open = (cookieValue: string): SessionRecord | null => {\n const raw = Buffer.from(cookieValue, \"base64url\");\n if (raw.length <= IV_BYTES + TAG_BYTES) return null;\n\n try {\n const decipher = createDecipheriv(\"aes-256-gcm\", key, raw.subarray(0, IV_BYTES));\n decipher.setAuthTag(raw.subarray(raw.length - TAG_BYTES));\n const json = Buffer.concat([\n decipher.update(raw.subarray(IV_BYTES, raw.length - TAG_BYTES)),\n decipher.final(),\n ]).toString(\"utf8\");\n return parseRecord(json);\n } catch {\n // Forged, truncated, or sealed with a secret that has since rotated.\n return null;\n }\n };\n\n return {\n names: cookieNames(config.cookieSecure),\n\n create(identity) {\n const now = Date.now();\n const record: SessionRecord = {\n identity: {\n ...identity,\n groups: identity.groups.filter((group) => admitted.has(groupName(group))),\n },\n csrfToken: randomToken(32),\n createdAt: new Date(now).toISOString(),\n refreshedAt: new Date(now).toISOString(),\n expiresAt: nextExpiry(now, now),\n };\n return { record, cookie: seal(record) };\n },\n\n resolve(cookieValue) {\n if (!cookieValue) return null;\n const record = open(cookieValue);\n if (!record || Date.parse(record.expiresAt) <= Date.now()) return null;\n return record;\n },\n\n refresh(record) {\n const now = Date.now();\n if (now - Date.parse(record.refreshedAt) < REFRESH_INTERVAL_MS) return null;\n\n const next: SessionRecord = {\n ...record,\n refreshedAt: new Date(now).toISOString(),\n expiresAt: nextExpiry(Date.parse(record.createdAt), now),\n };\n return { record: next, cookie: seal(next) };\n },\n\n sessionCookieOptions() {\n return {\n path: \"/\",\n httpOnly: true,\n secure: config.cookieSecure,\n // Lax keeps the cookie on top-level navigations back to the admin\n // while blocking it on cross-site form posts.\n sameSite: \"Lax\",\n maxAge: Math.floor(ttlMs / 1000),\n };\n },\n\n csrfCookieOptions() {\n return {\n path: \"/\",\n // Readable by the SPA on purpose: it echoes the value in a header,\n // which is what makes the double-submit check work.\n httpOnly: false,\n secure: config.cookieSecure,\n sameSite: \"Lax\",\n maxAge: Math.floor(ttlMs / 1000),\n };\n },\n\n clearedCookieOptions() {\n return {\n path: \"/\",\n httpOnly: true,\n secure: config.cookieSecure,\n sameSite: \"Lax\",\n maxAge: 0,\n };\n },\n };\n}\n\n/* ------------------------------------------------------------------ *\n * Starting one\n * ------------------------------------------------------------------ */\n\n/** Issues the session cookies for a browser that has just been identified. */\nexport function establishSession(\n c: Context<Env>,\n sessions: SessionService,\n identity: SessionIdentity,\n): void {\n const { record, cookie } = sessions.create(identity);\n\n setCookie(c, sessions.names.session, cookie, sessions.sessionCookieOptions());\n setCookie(c, sessions.names.csrf, record.csrfToken, sessions.csrfCookieOptions());\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@micacms/auth-oidc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-rc.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The server-only OIDC gate for Mica: sign-in, sessions and admission around @micacms/runtime. Never enters a browser bundle, and never a dependency of the local editor.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"hono": "^4.13.7",
|
|
29
29
|
"openid-client": "^6.8.5",
|
|
30
30
|
"zod": "^4.3.6",
|
|
31
|
-
"@micacms/
|
|
32
|
-
"@micacms/
|
|
31
|
+
"@micacms/core": "0.5.0-rc.2",
|
|
32
|
+
"@micacms/runtime": "0.5.0-rc.2"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "^22.20.1",
|