@cat-factory/server 0.223.0 → 0.224.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.
Files changed (46) hide show
  1. package/dist/auth/oidc/OidcClient.d.ts +86 -0
  2. package/dist/auth/oidc/OidcClient.d.ts.map +1 -0
  3. package/dist/auth/oidc/OidcClient.js +271 -0
  4. package/dist/auth/oidc/OidcClient.js.map +1 -0
  5. package/dist/auth/oidc/claims.d.ts +97 -0
  6. package/dist/auth/oidc/claims.d.ts.map +1 -0
  7. package/dist/auth/oidc/claims.js +149 -0
  8. package/dist/auth/oidc/claims.js.map +1 -0
  9. package/dist/auth/oidc/discovery.d.ts +51 -0
  10. package/dist/auth/oidc/discovery.d.ts.map +1 -0
  11. package/dist/auth/oidc/discovery.js +165 -0
  12. package/dist/auth/oidc/discovery.js.map +1 -0
  13. package/dist/auth/signing.d.ts +9 -0
  14. package/dist/auth/signing.d.ts.map +1 -1
  15. package/dist/auth/signing.js +9 -0
  16. package/dist/auth/signing.js.map +1 -1
  17. package/dist/config/misconfiguredApp.d.ts.map +1 -1
  18. package/dist/config/misconfiguredApp.js +14 -1
  19. package/dist/config/misconfiguredApp.js.map +1 -1
  20. package/dist/config/problems.js +1 -1
  21. package/dist/config/problems.js.map +1 -1
  22. package/dist/config/sso.d.ts +39 -0
  23. package/dist/config/sso.d.ts.map +1 -0
  24. package/dist/config/sso.js +169 -0
  25. package/dist/config/sso.js.map +1 -0
  26. package/dist/config/types.d.ts +41 -1
  27. package/dist/config/types.d.ts.map +1 -1
  28. package/dist/index.d.ts +7 -2
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +10 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/modules/auth/AuthController.d.ts +0 -18
  33. package/dist/modules/auth/AuthController.d.ts.map +1 -1
  34. package/dist/modules/auth/AuthController.js +18 -150
  35. package/dist/modules/auth/AuthController.js.map +1 -1
  36. package/dist/modules/auth/loginFlow.d.ts +56 -0
  37. package/dist/modules/auth/loginFlow.d.ts.map +1 -0
  38. package/dist/modules/auth/loginFlow.js +162 -0
  39. package/dist/modules/auth/loginFlow.js.map +1 -0
  40. package/dist/modules/auth/ssoRoutes.d.ts +4 -0
  41. package/dist/modules/auth/ssoRoutes.d.ts.map +1 -0
  42. package/dist/modules/auth/ssoRoutes.js +294 -0
  43. package/dist/modules/auth/ssoRoutes.js.map +1 -0
  44. package/dist/modules/localSettings/MothershipConnectController.js +1 -1
  45. package/dist/modules/localSettings/MothershipConnectController.js.map +1 -1
  46. package/package.json +9 -8
@@ -0,0 +1,56 @@
1
+ import type { Context } from 'hono';
2
+ import type { UserRecord } from '@cat-factory/kernel';
3
+ import { type SessionUser, TOKEN_AUDIENCE } from '../../auth/signing.js';
4
+ import type { AuthConfig } from '../../config/types.js';
5
+ import type { AppEnv } from '../../http/env.js';
6
+ /** How long a login round-trip's signed state stays valid. */
7
+ export declare const OAUTH_STATE_TTL_MS: number;
8
+ /** Browser-binding cookie for an OAuth round-trip (the CSRF pair for the signed `state`). */
9
+ export declare const OAUTH_STATE_COOKIE = "cf_oauth_state";
10
+ export interface OAuthState {
11
+ aud: typeof TOKEN_AUDIENCE.oauthState;
12
+ nonce: string;
13
+ /** Where to send the browser (with the token) after a successful login. */
14
+ redirect: string;
15
+ /** Optional invite token to redeem after a brand-new Google/GitHub signup. */
16
+ invite?: string;
17
+ exp: number;
18
+ }
19
+ export declare function authConfig<E extends AppEnv>(c: Context<E>): AuthConfig;
20
+ /**
21
+ * Choose the post-login landing URL from the (untrusted) `redirect` query. The
22
+ * session token is appended as a fragment, so an unrestricted redirect is a
23
+ * token-exfiltration primitive — only same-origin, an explicitly allowlisted origin, or a
24
+ * loopback host (the caller's own machine) is honoured, else the request origin.
25
+ */
26
+ export declare function pickPostLoginRedirect(requested: string | undefined, requestOrigin: string, cfg: Pick<AuthConfig, 'successRedirectUrl' | 'allowedRedirectOrigins'>): string;
27
+ export declare function resolveRedirect<E extends AppEnv>(c: Context<E>, cfg: AuthConfig): string;
28
+ /** Append the session token as a URL fragment on the landing URL. */
29
+ export declare function withToken(redirect: string, token: string): string;
30
+ /** Build the SessionUser surface from a canonical user + chosen display login. */
31
+ export declare function sessionUser(user: UserRecord, login: string): SessionUser;
32
+ /**
33
+ * Mint a user SESSION token, returning the signed token and the exact `exp` it committed to so a
34
+ * caller can report the real expiry without a second clock read. Shared by every login path AND
35
+ * the local-mode mothership-connect controller, so the session claim shape lives in one place.
36
+ */
37
+ export declare function mintSession(cfg: AuthConfig, user: SessionUser): Promise<{
38
+ token: string;
39
+ exp: number;
40
+ }>;
41
+ /** Whether an email's domain is on the self-signup allowlist. */
42
+ export declare function emailDomainAllowed(email: string, cfg: AuthConfig): boolean;
43
+ /**
44
+ * Set a round-trip's browser-binding cookie. `Lax` is deliberate and sufficient: every callback
45
+ * this covers arrives as a top-level GET navigation, which Lax permits.
46
+ */
47
+ export declare function setRoundTripCookie<E extends AppEnv>(c: Context<E>, name: string, value: string): void;
48
+ /** Verify + single-use the OAuth state (signature, expiry, browser-binding cookie). */
49
+ export declare function consumeState<E extends AppEnv>(c: Context<E>, cfg: AuthConfig): Promise<OAuthState | null>;
50
+ /** Begin a redirect round-trip: sign the state and bind it to the browser with a cookie. */
51
+ export declare function beginRoundTrip<E extends AppEnv>(c: Context<E>, cfg: AuthConfig): Promise<string>;
52
+ export declare function peekInvite<E extends AppEnv>(c: Context<E>, token: string): Promise<any>;
53
+ /** Whether a sign-in email matches the address an invitation was sent to. */
54
+ export declare function emailMatchesInvite(signInEmail: string | null | undefined, inviteEmail: string): boolean;
55
+ export declare function acceptInvite<E extends AppEnv>(c: Context<E>, token: string, userId: string, userEmail: string | null): Promise<void>;
56
+ //# sourceMappingURL=loginFlow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loginFlow.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/loginFlow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAGnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAGL,KAAK,WAAW,EAChB,cAAc,EACf,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAkB/C,8DAA8D;AAC9D,eAAO,MAAM,kBAAkB,QAAiB,CAAA;AAEhD,6FAA6F;AAC7F,eAAO,MAAM,kBAAkB,mBAAmB,CAAA;AAElD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,OAAO,cAAc,CAAC,UAAU,CAAA;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAA;IAChB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,UAAU,CAEtE;AAcD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,IAAI,CAAC,UAAU,EAAE,oBAAoB,GAAG,wBAAwB,CAAC,GACrE,MAAM,CAkBR;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,CAExF;AAED,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjE;AAED,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAQxE;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,UAAU,EACf,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAIzC;AAED,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAK1E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EACjD,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,IAAI,CAQN;AAED,uFAAuF;AACvF,wBAAsB,YAAY,CAAC,CAAC,SAAS,MAAM,EACjD,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EACb,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAQ5B;AAED,4FAA4F;AAC5F,wBAAsB,cAAc,CAAC,CAAC,SAAS,MAAM,EACnD,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EACb,GAAG,EAAE,UAAU,GACd,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED,wBAAsB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,gBAG9E;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACtC,WAAW,EAAE,MAAM,GAClB,OAAO,CAET;AAED,wBAAsB,YAAY,CAAC,CAAC,SAAS,MAAM,EACjD,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAAG,IAAI,GACvB,OAAO,CAAC,IAAI,CAAC,CAWf"}
@@ -0,0 +1,162 @@
1
+ import { deleteCookie, getCookie, setCookie } from 'hono/cookie';
2
+ import { ConflictError, NotFoundError } from '@cat-factory/kernel';
3
+ import { HmacSigner, TOKEN_AUDIENCE, } from '../../auth/signing.js';
4
+ // ---------------------------------------------------------------------------
5
+ // The shared mechanics of a BROWSER login round-trip, used by every provider that redirects:
6
+ // GitHub OAuth, Google OAuth, and enterprise SSO.
7
+ //
8
+ // Extracted from `AuthController` when SSO landed, because the alternative was a second copy of
9
+ // the CSRF state, the redirect allow-listing and the session mint — the three pieces where a
10
+ // divergence is a vulnerability rather than an inconsistency:
11
+ //
12
+ // - the signed, cookie-bound `state` nonce is the CSRF defence, and "one implementation" is what
13
+ // the SSO design committed to;
14
+ // - `pickPostLoginRedirect` guards a token-EXFILTRATION primitive (the session token rides the
15
+ // landing URL's fragment), so a provider with its own laxer copy would hand an attacker the
16
+ // session of anyone who clicked their link;
17
+ // - `mintSession` is the one place the session claim shape lives.
18
+ // ---------------------------------------------------------------------------
19
+ /** How long a login round-trip's signed state stays valid. */
20
+ export const OAUTH_STATE_TTL_MS = 10 * 60 * 1000;
21
+ /** Browser-binding cookie for an OAuth round-trip (the CSRF pair for the signed `state`). */
22
+ export const OAUTH_STATE_COOKIE = 'cf_oauth_state';
23
+ export function authConfig(c) {
24
+ return c.get('container').config.auth;
25
+ }
26
+ /**
27
+ * A loopback host (the user's OWN machine): `localhost`, the `127.0.0.0/8` block, or IPv6 `::1`.
28
+ * A redirect to one of these is not an exfiltration vector — capturing the fragment there means
29
+ * already running a server on the victim's own machine. This is what lets a mothership honour the
30
+ * post-login redirect back to a mothership-mode LOCAL node (`http://localhost:PORT`), which is
31
+ * neither same-origin nor pre-allowlisted, without an operator hand-listing every dev port.
32
+ */
33
+ function isLoopbackRedirect(url) {
34
+ const host = url.hostname.toLowerCase().replace(/^\[|\]$/g, '');
35
+ return host === 'localhost' || host === '::1' || /^127\.\d+\.\d+\.\d+$/.test(host);
36
+ }
37
+ /**
38
+ * Choose the post-login landing URL from the (untrusted) `redirect` query. The
39
+ * session token is appended as a fragment, so an unrestricted redirect is a
40
+ * token-exfiltration primitive — only same-origin, an explicitly allowlisted origin, or a
41
+ * loopback host (the caller's own machine) is honoured, else the request origin.
42
+ */
43
+ export function pickPostLoginRedirect(requested, requestOrigin, cfg) {
44
+ if (cfg.successRedirectUrl)
45
+ return cfg.successRedirectUrl;
46
+ const fallback = `${requestOrigin}/`;
47
+ if (!requested)
48
+ return fallback;
49
+ try {
50
+ const url = new URL(requested);
51
+ if (url.protocol !== 'http:' && url.protocol !== 'https:')
52
+ return fallback;
53
+ if (url.origin === requestOrigin ||
54
+ cfg.allowedRedirectOrigins.includes(url.origin) ||
55
+ isLoopbackRedirect(url)) {
56
+ return requested;
57
+ }
58
+ }
59
+ catch {
60
+ // fall through to the safe origin-relative default
61
+ }
62
+ return fallback;
63
+ }
64
+ export function resolveRedirect(c, cfg) {
65
+ return pickPostLoginRedirect(c.req.query('redirect'), new URL(c.req.url).origin, cfg);
66
+ }
67
+ /** Append the session token as a URL fragment on the landing URL. */
68
+ export function withToken(redirect, token) {
69
+ const url = new URL(redirect);
70
+ url.hash = `token=${token}`;
71
+ return url.toString();
72
+ }
73
+ /** Build the SessionUser surface from a canonical user + chosen display login. */
74
+ export function sessionUser(user, login) {
75
+ return {
76
+ id: user.id,
77
+ login,
78
+ name: user.name,
79
+ avatarUrl: user.avatarUrl,
80
+ email: user.email,
81
+ };
82
+ }
83
+ /**
84
+ * Mint a user SESSION token, returning the signed token and the exact `exp` it committed to so a
85
+ * caller can report the real expiry without a second clock read. Shared by every login path AND
86
+ * the local-mode mothership-connect controller, so the session claim shape lives in one place.
87
+ */
88
+ export async function mintSession(cfg, user) {
89
+ const exp = Date.now() + cfg.sessionTtlMs;
90
+ const session = { ...user, aud: TOKEN_AUDIENCE.session, exp };
91
+ return { token: await new HmacSigner(cfg.sessionSecret).sign(session), exp };
92
+ }
93
+ /** Whether an email's domain is on the self-signup allowlist. */
94
+ export function emailDomainAllowed(email, cfg) {
95
+ const at = email.lastIndexOf('@');
96
+ if (at < 0)
97
+ return false;
98
+ const domain = email.slice(at + 1).toLowerCase();
99
+ return cfg.allowedEmailDomains.includes(domain);
100
+ }
101
+ /**
102
+ * Set a round-trip's browser-binding cookie. `Lax` is deliberate and sufficient: every callback
103
+ * this covers arrives as a top-level GET navigation, which Lax permits.
104
+ */
105
+ export function setRoundTripCookie(c, name, value) {
106
+ setCookie(c, name, value, {
107
+ httpOnly: true,
108
+ secure: new URL(c.req.url).protocol === 'https:',
109
+ sameSite: 'Lax',
110
+ path: '/auth',
111
+ maxAge: OAUTH_STATE_TTL_MS / 1000,
112
+ });
113
+ }
114
+ /** Verify + single-use the OAuth state (signature, expiry, browser-binding cookie). */
115
+ export async function consumeState(c, cfg) {
116
+ const state = await new HmacSigner(cfg.sessionSecret).verify(c.req.query('state'), {
117
+ aud: TOKEN_AUDIENCE.oauthState,
118
+ });
119
+ const boundNonce = getCookie(c, OAUTH_STATE_COOKIE);
120
+ deleteCookie(c, OAUTH_STATE_COOKIE, { path: '/auth' });
121
+ if (!state || !boundNonce || boundNonce !== state.nonce)
122
+ return null;
123
+ return state;
124
+ }
125
+ /** Begin a redirect round-trip: sign the state and bind it to the browser with a cookie. */
126
+ export async function beginRoundTrip(c, cfg) {
127
+ const nonce = crypto.randomUUID();
128
+ const state = {
129
+ aud: TOKEN_AUDIENCE.oauthState,
130
+ nonce,
131
+ redirect: resolveRedirect(c, cfg),
132
+ ...(c.req.query('invite') ? { invite: c.req.query('invite') } : {}),
133
+ exp: Date.now() + OAUTH_STATE_TTL_MS,
134
+ };
135
+ const signedState = await new HmacSigner(cfg.sessionSecret).sign(state);
136
+ setRoundTripCookie(c, OAUTH_STATE_COOKIE, nonce);
137
+ return signedState;
138
+ }
139
+ export async function peekInvite(c, token) {
140
+ const inv = c.get('container').invitations;
141
+ return inv ? inv.peek(token) : null;
142
+ }
143
+ /** Whether a sign-in email matches the address an invitation was sent to. */
144
+ export function emailMatchesInvite(signInEmail, inviteEmail) {
145
+ return !!signInEmail && signInEmail.toLowerCase().trim() === inviteEmail;
146
+ }
147
+ export async function acceptInvite(c, token, userId, userEmail) {
148
+ const inv = c.get('container').invitations;
149
+ if (!inv)
150
+ return;
151
+ try {
152
+ await inv.accept(token, userId, userEmail);
153
+ }
154
+ catch (err) {
155
+ // Expected invite states (expired / already-used / wrong email) must not block an
156
+ // otherwise-valid login; an unexpected infra error should still surface.
157
+ if (err instanceof ConflictError || err instanceof NotFoundError)
158
+ return;
159
+ throw err;
160
+ }
161
+ }
162
+ //# sourceMappingURL=loginFlow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loginFlow.js","sourceRoot":"","sources":["../../../src/modules/auth/loginFlow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Hono } from 'hono';
2
+ import type { AppEnv } from '../../http/env.js';
3
+ export declare function registerSsoRoutes(app: Hono<AppEnv>): void;
4
+ //# sourceMappingURL=ssoRoutes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssoRoutes.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/ssoRoutes.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAqBhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAuG/C,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAqFzD"}
@@ -0,0 +1,294 @@
1
+ import { SSO_ERROR_FRAGMENT_KEY, ssoCallbackContract, ssoLoginContract, } from '@cat-factory/contracts';
2
+ import { buildHonoRoute } from '@toad-contracts/hono';
3
+ import { deleteCookie, getCookie } from 'hono/cookie';
4
+ import { UnavailableError, oidcIdentitySubject } from '@cat-factory/kernel';
5
+ import { OidcClient, OidcFlowError, createPkcePair, ssoNotConfigured, } from '../../auth/oidc/OidcClient.js';
6
+ import { OidcProviderDirectory } from '../../auth/oidc/discovery.js';
7
+ import { judgeSsoAdmission, needsUserinfo, readSsoIdentity, userinfoMatchesSubject, } from '../../auth/oidc/claims.js';
8
+ import { HmacSigner, TOKEN_AUDIENCE } from '../../auth/signing.js';
9
+ import { requestLogger } from '../../http/requestLogging.js';
10
+ import { OAUTH_STATE_TTL_MS, acceptInvite, authConfig, emailMatchesInvite, mintSession, peekInvite, pickPostLoginRedirect, resolveRedirect, sessionUser, setRoundTripCookie, withToken, } from './loginFlow.js';
11
+ // ---------------------------------------------------------------------------
12
+ // Enterprise SSO sign-in: `GET /auth/sso/login` → the IdP → `GET /auth/sso/callback`.
13
+ //
14
+ // ONE pair of routes serves every OpenID Connect provider, because the provider's own discovery
15
+ // document supplies the endpoints (see `auth/oidc/discovery.ts`). What this module owns is the
16
+ // round-trip's STATE and its refusals.
17
+ //
18
+ // The state differs from the GitHub/Google flow in one way that matters. Those carry a signed
19
+ // state token in the URL and bind it to a cookie holding just its nonce. SSO cannot: PKCE's
20
+ // `code_verifier` and OIDC's `nonce` are SECRETS that must not travel in a URL — a verifier
21
+ // visible beside the code it protects protects nothing. So the whole round-trip rides in the
22
+ // httpOnly cookie (signed, audience-pinned with the SAME `HmacSigner` the OAuth flow uses, so
23
+ // CSRF protection stays one implementation) and only an opaque nonce goes in the `state`
24
+ // parameter. That also means the post-login redirect target cannot be tampered with in the URL,
25
+ // which is strictly stronger than the OAuth leg.
26
+ //
27
+ // Refusals REDIRECT rather than rendering an error envelope: a browser mid-redirect that lands on
28
+ // raw JSON has no way back, and the reason is a closed vocabulary the SPA maps to translated copy
29
+ // (`SSO_ERROR_REASONS`). The redirect target is only ever a TRUSTED one — the cookie's own
30
+ // recorded target, or `pickPostLoginRedirect` with no requested value — never a query parameter,
31
+ // because the failure path must not become the open redirect the success path is guarded against.
32
+ // ---------------------------------------------------------------------------
33
+ /** The httpOnly cookie carrying one SSO round-trip. Distinct from the OAuth flow's. */
34
+ const SSO_STATE_COOKIE = 'cf_sso_state';
35
+ function ssoConfig(c) {
36
+ const cfg = authConfig(c).sso;
37
+ if (!cfg)
38
+ ssoNotConfigured();
39
+ return cfg;
40
+ }
41
+ /**
42
+ * The redirect_uri, which must match what is registered with the IdP EXACTLY. Explicit
43
+ * configuration wins, because a deployment behind a proxy or a custom domain sees a request
44
+ * origin that is not its public one, and a derived value would then be rejected by the provider
45
+ * with the least helpful error it has (`invalid_grant`).
46
+ */
47
+ function ssoCallbackUrl(c, cfg) {
48
+ if (cfg.redirectUrl)
49
+ return cfg.redirectUrl;
50
+ return `${new URL(c.req.url).origin}/auth/sso/callback`;
51
+ }
52
+ /**
53
+ * Build the OIDC client for this request. A fresh instance per request is deliberate: the
54
+ * expensive part (the discovery document) lives in the shared app cache, so the client itself
55
+ * holds no state worth reusing and none worth leaking between requests.
56
+ */
57
+ function ssoClient(c, cfg) {
58
+ const logger = requestLogger(c);
59
+ return new OidcClient({
60
+ config: cfg,
61
+ directory: new OidcProviderDirectory({
62
+ cache: c.get('container').caches?.ssoDiscovery,
63
+ logger,
64
+ }),
65
+ logger,
66
+ });
67
+ }
68
+ /** Land the browser back on the SPA with a machine-readable reason instead of a session. */
69
+ function refuse(target, reason) {
70
+ const url = new URL(target);
71
+ url.hash = `${SSO_ERROR_FRAGMENT_KEY}=${reason}`;
72
+ return url.toString();
73
+ }
74
+ export function registerSsoRoutes(app) {
75
+ buildHonoRoute(app, ssoLoginContract, async (c) => {
76
+ const cfg = authConfig(c);
77
+ const sso = ssoConfig(c);
78
+ const { verifier, challenge } = await createPkcePair();
79
+ const trip = {
80
+ aud: TOKEN_AUDIENCE.ssoState,
81
+ nonce: crypto.randomUUID(),
82
+ verifier,
83
+ idNonce: crypto.randomUUID(),
84
+ redirect: resolveRedirect(c, cfg),
85
+ ...(c.req.query('invite') ? { invite: c.req.query('invite') } : {}),
86
+ exp: Date.now() + OAUTH_STATE_TTL_MS,
87
+ };
88
+ setRoundTripCookie(c, SSO_STATE_COOKIE, await new HmacSigner(cfg.sessionSecret).sign(trip));
89
+ // Resolving the provider can fail (an unreachable IdP, a malformed discovery document). It
90
+ // throws an `UnavailableError` naming which, and the shared error handler renders it: this is
91
+ // the one leg where an envelope is right, because nothing has redirected yet and the operator
92
+ // is the audience.
93
+ const url = await ssoClient(c, sso).authorizeUrl({
94
+ redirectUri: ssoCallbackUrl(c, sso),
95
+ state: trip.nonce,
96
+ nonce: trip.idNonce,
97
+ codeChallenge: challenge,
98
+ });
99
+ return c.redirect(url);
100
+ });
101
+ buildHonoRoute(app, ssoCallbackContract, async (c) => {
102
+ const cfg = authConfig(c);
103
+ const sso = ssoConfig(c);
104
+ const trip = await consumeRoundTrip(c, cfg);
105
+ // With no verified round-trip there is no recorded landing URL, so fall back to the
106
+ // deployment's own configured target (or its origin) — never the request's `redirect` query,
107
+ // which is exactly the untrusted value the success path allow-lists.
108
+ const fallback = pickPostLoginRedirect(undefined, new URL(c.req.url).origin, cfg);
109
+ if (!trip)
110
+ return c.redirect(refuse(fallback, 'state_invalid'));
111
+ // The IdP's own refusal (`access_denied` when a user cancels or the app is not assigned to
112
+ // them) is reported as itself rather than as a token failure: there is nothing on this side
113
+ // to fix, and saying "invalid token" would send an operator hunting one.
114
+ if (c.req.query('error')) {
115
+ requestLogger(c).info('sso.provider_denied', { error: c.req.query('error') });
116
+ return c.redirect(refuse(trip.redirect, 'provider_denied'));
117
+ }
118
+ const code = c.req.query('code');
119
+ if (!code)
120
+ return c.redirect(refuse(trip.redirect, 'state_invalid'));
121
+ const client = ssoClient(c, sso);
122
+ let resolved;
123
+ try {
124
+ resolved = await resolveIdentity(client, sso, {
125
+ code,
126
+ redirectUri: ssoCallbackUrl(c, sso),
127
+ trip,
128
+ logger: requestLogger(c),
129
+ });
130
+ }
131
+ catch (err) {
132
+ // An IdP that stopped answering mid-round-trip is an OUTAGE, not a bad token and not this
133
+ // deployment's credentials, so it gets its own reason. It also has to REDIRECT: on the login
134
+ // leg an envelope is right (nothing has redirected yet, the operator is the audience), but
135
+ // here the browser is mid-flow and raw JSON leaves it with no way back.
136
+ if (err instanceof UnavailableError) {
137
+ requestLogger(c).warn('sso.provider_unreachable', { detail: err.message });
138
+ return c.redirect(refuse(trip.redirect, 'provider_unreachable'));
139
+ }
140
+ if (!(err instanceof OidcFlowError))
141
+ throw err;
142
+ // The message names the operator-actionable cause (a wrong secret, a redirect_uri the IdP
143
+ // does not hold, a clock skew); the user gets the reason code. Logged at WARN because a
144
+ // deployment whose SSO cannot complete is broken, not busy.
145
+ requestLogger(c).warn(`sso.${err.reason}`, { detail: err.message });
146
+ return c.redirect(refuse(trip.redirect, err.reason));
147
+ }
148
+ const { identity, issuer } = resolved;
149
+ if (!identity)
150
+ return c.redirect(refuse(trip.redirect, 'subject_missing'));
151
+ const admission = judgeSsoAdmission(identity, sso);
152
+ if (!admission.allowed) {
153
+ requestLogger(c).info('sso.refused', { reason: admission.reason, login: identity.login });
154
+ return c.redirect(refuse(trip.redirect, admission.reason));
155
+ }
156
+ const token = await establishSession(c, cfg, identity, issuer, trip);
157
+ return c.redirect(withToken(trip.redirect, token));
158
+ });
159
+ }
160
+ /**
161
+ * Exchange the code, verify the ID token, and merge in userinfo when — and only when — a claim
162
+ * admission depends on is missing from the token. `identity` is null when the verified token
163
+ * carries no `sub`, the one shape that leaves nothing to key an identity on.
164
+ *
165
+ * Returns the DISCOVERED issuer alongside it, so the caller keying the user's identity on it does
166
+ * not resolve the provider a second time: that second read is what put an IdP outage AFTER the
167
+ * admission decision, where nothing was left to report it with.
168
+ */
169
+ async function resolveIdentity(client, sso, params) {
170
+ const tokens = await client.exchangeCode({
171
+ code: params.code,
172
+ redirectUri: params.redirectUri,
173
+ codeVerifier: params.trip.verifier,
174
+ });
175
+ const claims = (await client.verifyIdToken(tokens.idToken, {
176
+ nonce: params.trip.idNonce,
177
+ }));
178
+ let merged = claims;
179
+ if (tokens.accessToken && needsUserinfo(claims, sso)) {
180
+ const extra = await client.fetchUserInfo(tokens.accessToken);
181
+ // The ID token's claims WIN over userinfo's: the token is signed and the userinfo response is
182
+ // only bearer-authenticated, so on a disagreement the verified half is authoritative. `sub`
183
+ // in particular must never be taken from userinfo.
184
+ //
185
+ // And the response is only merged AT ALL when it describes the same subject the token did
186
+ // (OIDC Core 5.3.2): spreading `claims` last protects `sub` itself, but `email` and `groups`
187
+ // ride the same response and both decide admission, so another subject's response would
188
+ // satisfy a group gate with somebody else's membership. Dropped LOUDLY, because the visible
189
+ // consequence otherwise is a `group_required` refusal blamed on the operator's group names.
190
+ if (extra && userinfoMatchesSubject(extra, claims))
191
+ merged = { ...extra, ...claims };
192
+ else if (extra) {
193
+ params.logger.warn('sso.userinfo.subject_mismatch', {
194
+ // Separates a non-conformant provider OMITTING the required claim (an operator fixes which
195
+ // claims it releases) from a response genuinely describing somebody else (alarming, and a
196
+ // different conversation). Neither subject value is logged.
197
+ userinfoHasSub: typeof extra.sub === 'string' && extra.sub.trim() !== '',
198
+ });
199
+ }
200
+ }
201
+ const { metadata } = await client.provider();
202
+ return { identity: readSsoIdentity(merged, sso), issuer: metadata.issuer };
203
+ }
204
+ /**
205
+ * Resolve the canonical user for a verified SSO identity and mint its session.
206
+ *
207
+ * The subject is `<discovered issuer>#<sub>`, never the email: emails are reassigned inside orgs
208
+ * and some directories let a user change their own, so keying on one would hand a departed
209
+ * employee's account to whoever inherits their address.
210
+ */
211
+ async function establishSession(c, cfg, identity, issuer, trip) {
212
+ const container = c.get('container');
213
+ const user = await container.userService.findOrCreateByIdentity('oidc', oidcIdentitySubject(issuer, identity.sub), {
214
+ name: identity.name,
215
+ email: identity.email,
216
+ emailVerified: identity.emailVerified,
217
+ avatarUrl: identity.avatarUrl,
218
+ metadata: { issuer, login: identity.login },
219
+ });
220
+ await container.accountService.ensurePersonalAccount({
221
+ id: user.id,
222
+ login: identity.login,
223
+ name: user.name,
224
+ });
225
+ // An SSO user reached here through the IdP's own app assignment, so an invite is not what
226
+ // ADMITTED them — it only decides which org they join. Honoured when present (a person invited
227
+ // by email who then signs in with SSO), and bound to the invited address exactly as every other
228
+ // provider binds it, so a leaked link cannot pull an arbitrary directory user into an org.
229
+ if (trip.invite) {
230
+ const invited = await peekInvite(c, trip.invite);
231
+ if (invited && emailMatchesInvite(identity.email, invited.email)) {
232
+ await acceptInvite(c, trip.invite, user.id, user.email);
233
+ }
234
+ }
235
+ const { token } = await mintSession(cfg, sessionUser(user, identity.login));
236
+ logSignIn(requestLogger(c), user.id, identity, issuer);
237
+ return token;
238
+ }
239
+ /**
240
+ * One line per successful SSO sign-in, at INFO.
241
+ *
242
+ * Deliberate: an org adopting SSO is doing it to answer "who has access", and a login that leaves
243
+ * no trace answers nothing. Group memberships are logged as a COUNT rather than a list — the list
244
+ * is directory data of unbounded size, and its presence or absence is what diagnoses a
245
+ * `group_required` refusal.
246
+ */
247
+ function logSignIn(logger, userId, identity, issuer) {
248
+ logger.info('sso.signed_in', {
249
+ userId,
250
+ issuer,
251
+ login: identity.login,
252
+ emailVerified: identity.emailVerified,
253
+ groupCount: identity.groups.length,
254
+ });
255
+ }
256
+ /**
257
+ * Verify + single-use the round-trip cookie, and check it against the `state` parameter the IdP
258
+ * echoed back. Returns null on any mismatch, which the caller reports as `state_invalid`.
259
+ *
260
+ * The cookie is deleted whatever the outcome, so one round-trip can be completed exactly once —
261
+ * which is also what makes a captured callback URL useless on a second visit.
262
+ */
263
+ async function consumeRoundTrip(c, cfg) {
264
+ const raw = getCookie(c, SSO_STATE_COOKIE);
265
+ deleteCookie(c, SSO_STATE_COOKIE, { path: '/auth' });
266
+ const trip = await new HmacSigner(cfg.sessionSecret).verify(raw, {
267
+ aud: TOKEN_AUDIENCE.ssoState,
268
+ });
269
+ if (!isCompleteRoundTrip(trip))
270
+ return null;
271
+ const state = c.req.query('state');
272
+ if (!state || state !== trip.nonce)
273
+ return null;
274
+ return trip;
275
+ }
276
+ /**
277
+ * Whether a verified cookie payload actually carries the round-trip this leg needs.
278
+ *
279
+ * `HmacSigner.verify` proves THIS deployment signed the value and pins its audience; neither
280
+ * proves its SHAPE, and the generic parameter is a cast rather than a check. Without this, a
281
+ * payload missing the two secrets would flow on as `undefined`: a PKCE `code_verifier` of
282
+ * `"undefined"` in the token form and a nonce compared against `undefined`, both of which a
283
+ * conformant provider refuses — which is exactly why the check belongs here instead of resting on
284
+ * one being conformant.
285
+ */
286
+ function isCompleteRoundTrip(trip) {
287
+ const present = (value) => typeof value === 'string' && value !== '';
288
+ return (trip !== null &&
289
+ present(trip.nonce) &&
290
+ present(trip.verifier) &&
291
+ present(trip.idNonce) &&
292
+ present(trip.redirect));
293
+ }
294
+ //# sourceMappingURL=ssoRoutes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssoRoutes.js","sourceRoot":"","sources":["../../../src/modules/auth/ssoRoutes.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { connectMothershipContract } from '@cat-factory/contracts';
2
2
  import { buildHonoRoute } from '@toad-contracts/hono';
3
3
  import { Hono } from 'hono';
4
- import { mintSession } from '../auth/AuthController.js';
4
+ import { mintSession } from '../auth/loginFlow.js';
5
5
  import { UnavailableError } from '@cat-factory/kernel';
6
6
  /**
7
7
  * Local-mode mothership login: `POST /local/mothership/connect`.
@@ -1 +1 @@
1
- {"version":3,"file":"MothershipConnectController.js","sourceRoot":"","sources":["../../../src/modules/localSettings/MothershipConnectController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAEtD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,2BAA2B;IACzC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAU,CAAA;IAE9B,cAAc,CAAC,GAAG,EAAE,yBAAyB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACzD,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,iBAAiB,CAAA;QACtD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,gBAAgB,CACxB,sEAAsE,CACvE,CAAA;QACH,CAAC;QACD,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QACvC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC/C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,6FAA6F;YAC7F,yEAAyE;YACzE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,CAAA;YAC7D,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,EAAE,EAClF,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CACnB,CAAA;QACH,CAAC;QACD,6FAA6F;QAC7F,0FAA0F;QAC1F,yFAAyF;QACzF,yFAAyF;QACzF,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,IAAI,CAAA;QAC1C,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;QACxE,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAChF,GAAG,CACJ,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,GAAG,CAAA;AACZ,CAAC"}
1
+ {"version":3,"file":"MothershipConnectController.js","sourceRoot":"","sources":["../../../src/modules/localSettings/MothershipConnectController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAEtD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,2BAA2B;IACzC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAU,CAAA;IAE9B,cAAc,CAAC,GAAG,EAAE,yBAAyB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACzD,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,iBAAiB,CAAA;QACtD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,gBAAgB,CACxB,sEAAsE,CACvE,CAAA;QACH,CAAC;QACD,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QACvC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC/C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,6FAA6F;YAC7F,yEAAyE;YACzE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,CAAA;YAC7D,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,EAAE,EAClF,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CACnB,CAAA;QACH,CAAC;QACD,6FAA6F;QAC7F,0FAA0F;QAC1F,yFAAyF;QACzF,yFAAyF;QACzF,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,IAAI,CAAA;QAC1C,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;QACxE,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAChF,GAAG,CACJ,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,GAAG,CAAA;AACZ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/server",
3
- "version": "0.223.0",
3
+ "version": "0.224.0",
4
4
  "description": "Runtime-neutral HTTP layer for the Agent Architecture Board: the Hono controllers, middleware (auth/authz/CORS/error), request helpers and the gateway seams shared by every deployment facade (Cloudflare Worker, Node service).",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,16 +28,17 @@
28
28
  "@toad-contracts/hono": "0.3.2",
29
29
  "@toad-contracts/valibot": "0.5.0",
30
30
  "hono": "^4.13.0",
31
+ "jose": "^6.2.8",
31
32
  "pino": "^10.3.1",
32
33
  "valibot": "^1.4.2",
33
- "@cat-factory/agents": "0.113.0",
34
- "@cat-factory/contracts": "0.246.0",
35
- "@cat-factory/integrations": "0.131.0",
36
- "@cat-factory/kernel": "0.244.0",
34
+ "@cat-factory/agents": "0.114.0",
35
+ "@cat-factory/contracts": "0.247.0",
36
+ "@cat-factory/integrations": "0.131.1",
37
+ "@cat-factory/kernel": "0.245.0",
37
38
  "@cat-factory/mcp-server": "0.12.0",
38
- "@cat-factory/orchestration": "0.213.0",
39
- "@cat-factory/prompt-fragments": "0.15.72",
40
- "@cat-factory/spend": "0.15.9"
39
+ "@cat-factory/orchestration": "0.214.0",
40
+ "@cat-factory/prompt-fragments": "0.15.73",
41
+ "@cat-factory/spend": "0.15.10"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@types/node": "^26.1.2",