@monotykamary/localterm-server 2.34.0 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdp/cdp-client.d.ts +30 -0
- package/dist/cdp/cdp-client.d.ts.map +1 -1
- package/dist/cdp/cdp-client.js +80 -0
- package/dist/cdp/cdp-client.js.map +1 -1
- package/dist/constants.d.ts +17 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +27 -0
- package/dist/constants.js.map +1 -1
- package/dist/daemon-config-store.d.ts +2 -0
- package/dist/daemon-config-store.d.ts.map +1 -1
- package/dist/daemon-config-store.js +14 -1
- package/dist/daemon-config-store.js.map +1 -1
- package/dist/identity/credential-store.d.ts +18 -0
- package/dist/identity/credential-store.d.ts.map +1 -0
- package/dist/identity/credential-store.js +76 -0
- package/dist/identity/credential-store.js.map +1 -0
- package/dist/identity/factory.d.ts +3 -0
- package/dist/identity/factory.d.ts.map +1 -0
- package/dist/identity/factory.js +19 -0
- package/dist/identity/factory.js.map +1 -0
- package/dist/identity/header-provider.d.ts +3 -0
- package/dist/identity/header-provider.d.ts.map +1 -0
- package/dist/identity/header-provider.js +33 -0
- package/dist/identity/header-provider.js.map +1 -0
- package/dist/identity/oidc-provider.d.ts +4 -0
- package/dist/identity/oidc-provider.d.ts.map +1 -0
- package/dist/identity/oidc-provider.js +172 -0
- package/dist/identity/oidc-provider.js.map +1 -0
- package/dist/identity/passkey-provider.d.ts +3 -0
- package/dist/identity/passkey-provider.d.ts.map +1 -0
- package/dist/identity/passkey-provider.js +233 -0
- package/dist/identity/passkey-provider.js.map +1 -0
- package/dist/identity/proxy-allowlist.d.ts +5 -0
- package/dist/identity/proxy-allowlist.d.ts.map +1 -0
- package/dist/identity/proxy-allowlist.js +64 -0
- package/dist/identity/proxy-allowlist.js.map +1 -0
- package/dist/identity/resolve.d.ts +11 -0
- package/dist/identity/resolve.d.ts.map +1 -0
- package/dist/identity/resolve.js +57 -0
- package/dist/identity/resolve.js.map +1 -0
- package/dist/identity/session-cookie.d.ts +10 -0
- package/dist/identity/session-cookie.d.ts.map +1 -0
- package/dist/identity/session-cookie.js +92 -0
- package/dist/identity/session-cookie.js.map +1 -0
- package/dist/identity/types.d.ts +49 -0
- package/dist/identity/types.d.ts.map +1 -0
- package/dist/identity/types.js +2 -0
- package/dist/identity/types.js.map +1 -0
- package/dist/identity/user-store.d.ts +16 -0
- package/dist/identity/user-store.d.ts.map +1 -0
- package/dist/identity/user-store.js +77 -0
- package/dist/identity/user-store.js.map +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +112 -31
- package/dist/index.js.map +1 -1
- package/dist/protocol.d.ts +2 -1
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +1 -1
- package/dist/protocol.js.map +1 -1
- package/dist/schemas.d.ts +79 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +55 -1
- package/dist/schemas.js.map +1 -1
- package/dist/secret-store.d.ts.map +1 -1
- package/dist/secret-store.js +4 -1
- package/dist/secret-store.js.map +1 -1
- package/dist/session-automation.d.ts +7 -2
- package/dist/session-automation.d.ts.map +1 -1
- package/dist/session-automation.js +27 -8
- package/dist/session-automation.js.map +1 -1
- package/dist/session-manager.d.ts +20 -17
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/session-manager.js +63 -44
- package/dist/session-manager.js.map +1 -1
- package/dist/utils/timing-safe-equal.d.ts +2 -0
- package/dist/utils/timing-safe-equal.d.ts.map +1 -0
- package/dist/utils/timing-safe-equal.js +12 -0
- package/dist/utils/timing-safe-equal.js.map +1 -0
- package/package.json +4 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { getConnInfo } from "@hono/node-server/conninfo";
|
|
2
|
+
import { HTTP_STATUS_UNAUTHORIZED } from "../constants.js";
|
|
3
|
+
import { timingSafeEqualString } from "../utils/timing-safe-equal.js";
|
|
4
|
+
// Best-effort source-IP read for an HTTP (non-WS) request. @hono/node-server's
|
|
5
|
+
// conninfo reads the underlying socket's remoteAddress. Returns null when the
|
|
6
|
+
// adapter doesn't expose it (or the helper throws — never 500 a request over
|
|
7
|
+
// an identity read) so the caller falls back to "untrusted source" and ignores
|
|
8
|
+
// any identity header.
|
|
9
|
+
export const getRequestSourceIp = (context) => {
|
|
10
|
+
try {
|
|
11
|
+
const address = getConnInfo(context).remote.address;
|
|
12
|
+
return typeof address === "string" ? address : null;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
// Build the per-request identity resolver. With no provider configured it
|
|
19
|
+
// resolves to `null` for every request — the operator/legacy tier — so every
|
|
20
|
+
// request is the single authority and the registry stays unscoped,
|
|
21
|
+
// byte-identical to the no-auth behavior. Otherwise it delegates to the
|
|
22
|
+
// provider, injecting the caller-resolved source IP: the WS upgrade reads it
|
|
23
|
+
// from the raw socket (more authoritative than conninfo at upgrade time), HTTP
|
|
24
|
+
// routes via conninfo.
|
|
25
|
+
export const createIdentityResolver = (provider) => ({
|
|
26
|
+
resolve: (context, sourceIp = null) => provider ? provider.identify(context, sourceIp) : null,
|
|
27
|
+
});
|
|
28
|
+
export const toSessionOwner = (identity) => identity ? identity.user : null;
|
|
29
|
+
// The auth gate for providers that own their own login (passkey/oidc): reject a
|
|
30
|
+
// request with no valid session at the door (401) so it never reaches the
|
|
31
|
+
// session registry — unlike `header`, whose no-header case is the operator
|
|
32
|
+
// tier (denyUnauthenticated: false), there's no external proxy to vouch for an
|
|
33
|
+
// unauthenticated caller here, so silence can't mean admin. Exempts
|
|
34
|
+
// `/api/health` (readiness) and everything outside `/api` and `/ws` (the static
|
|
35
|
+
// terminal app + the `/auth` login flow must load before there's a session). A
|
|
36
|
+
// request carrying the daemon's operator bearer token (the CLI) is admitted as
|
|
37
|
+
// the operator tier — full access, no session — since the CLI can't run a
|
|
38
|
+
// WebAuthn/OIDC ceremony.
|
|
39
|
+
export const createAuthGateMiddleware = (provider, resolveIdentity) => async (context, next) => {
|
|
40
|
+
if (!provider?.denyUnauthenticated)
|
|
41
|
+
return await next();
|
|
42
|
+
const requestPath = context.req.path;
|
|
43
|
+
const isProtected = (requestPath === "/ws" || requestPath.startsWith("/api/")) && requestPath !== "/api/health";
|
|
44
|
+
if (!isProtected)
|
|
45
|
+
return await next();
|
|
46
|
+
const authorization = context.req.header("authorization");
|
|
47
|
+
if (provider.operatorToken &&
|
|
48
|
+
authorization &&
|
|
49
|
+
timingSafeEqualString(authorization, `Bearer ${provider.operatorToken}`)) {
|
|
50
|
+
return await next();
|
|
51
|
+
}
|
|
52
|
+
const identity = resolveIdentity(context, getRequestSourceIp(context));
|
|
53
|
+
if (!identity)
|
|
54
|
+
return context.json({ error: "unauthorized" }, HTTP_STATUS_UNAUTHORIZED);
|
|
55
|
+
await next();
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/identity/resolve.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAGtE,+EAA+E;AAC/E,8EAA8E;AAC9E,6EAA6E;AAC7E,+EAA+E;AAC/E,uBAAuB;AACvB,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAgB,EAAiB,EAAE;IACpE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;QACpD,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAMF,0EAA0E;AAC1E,6EAA6E;AAC7E,mEAAmE;AACnE,wEAAwE;AACxE,6EAA6E;AAC7E,+EAA+E;AAC/E,uBAAuB;AACvB,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,QAAiC,EAAoB,EAAE,CAAC,CAAC;IAC9F,OAAO,EAAE,CAAC,OAAgB,EAAE,WAA0B,IAAI,EAAmB,EAAE,CAC7E,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI;CACzD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAyB,EAAgB,EAAE,CACxE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAElC,gFAAgF;AAChF,0EAA0E;AAC1E,2EAA2E;AAC3E,+EAA+E;AAC/E,oEAAoE;AACpE,gFAAgF;AAChF,+EAA+E;AAC/E,+EAA+E;AAC/E,0EAA0E;AAC1E,0BAA0B;AAC1B,MAAM,CAAC,MAAM,wBAAwB,GACnC,CACE,QAAiC,EACjC,eAAgF,EAC7D,EAAE,CACvB,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IACtB,IAAI,CAAC,QAAQ,EAAE,mBAAmB;QAAE,OAAO,MAAM,IAAI,EAAE,CAAC;IACxD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IACrC,MAAM,WAAW,GACf,CAAC,WAAW,KAAK,KAAK,IAAI,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,WAAW,KAAK,aAAa,CAAC;IAC9F,IAAI,CAAC,WAAW;QAAE,OAAO,MAAM,IAAI,EAAE,CAAC;IACtC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IAC1D,IACE,QAAQ,CAAC,aAAa;QACtB,aAAa;QACb,qBAAqB,CAAC,aAAa,EAAE,UAAU,QAAQ,CAAC,aAAa,EAAE,CAAC,EACxE,CAAC;QACD,OAAO,MAAM,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;IACvE,IAAI,CAAC,QAAQ;QAAE,OAAO,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,wBAAwB,CAAC,CAAC;IACxF,MAAM,IAAI,EAAE,CAAC;AACf,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Context } from "hono";
|
|
2
|
+
import type { Identity } from "./types.js";
|
|
3
|
+
export declare const generateAuthSecret: () => string;
|
|
4
|
+
export declare const loadOrCreateAuthSecret: (filePath: string) => string;
|
|
5
|
+
export declare const signSessionToken: (secret: string, user: string) => string;
|
|
6
|
+
export declare const verifySessionToken: (secret: string, token: string) => string | null;
|
|
7
|
+
export declare const setSessionCookie: (context: Context, secret: string, user: string) => void;
|
|
8
|
+
export declare const clearSessionCookie: (context: Context) => void;
|
|
9
|
+
export declare const readSessionIdentity: (context: Context, secret: string) => Identity | null;
|
|
10
|
+
//# sourceMappingURL=session-cookie.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-cookie.d.ts","sourceRoot":"","sources":["../../src/identity/session-cookie.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAe3C,eAAO,MAAM,kBAAkB,QAAO,MACgB,CAAC;AAKvD,eAAO,MAAM,sBAAsB,GAAI,UAAU,MAAM,KAAG,MAazD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM,KAAG,MAO/D,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAAM,GAAG,IAmB3E,CAAC;AAsBF,eAAO,MAAM,gBAAgB,GAAI,SAAS,OAAO,EAAE,QAAQ,MAAM,EAAE,MAAM,MAAM,KAAG,IAOjF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,SAAS,OAAO,KAAG,IAErD,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,SAAS,OAAO,EAAE,QAAQ,MAAM,KAAG,QAAQ,GAAG,IAKjF,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { getCookie, setCookie } from "hono/cookie";
|
|
5
|
+
import { AUTH_COOKIE_MAX_AGE_SECONDS, AUTH_COOKIE_NAME, AUTH_SECRET_BYTES } from "../constants.js";
|
|
6
|
+
const sign = (secret, data) => createHmac("sha256", secret).update(data).digest("base64url");
|
|
7
|
+
export const generateAuthSecret = () => randomBytes(AUTH_SECRET_BYTES).toString("base64url");
|
|
8
|
+
// Read the persisted HMAC secret, generating + persisting a fresh one on the
|
|
9
|
+
// first run. Losing this file invalidates every live session (users re-log in),
|
|
10
|
+
// which is the correct failure mode — never silently reuse a weak/absent key.
|
|
11
|
+
export const loadOrCreateAuthSecret = (filePath) => {
|
|
12
|
+
try {
|
|
13
|
+
const existing = fs.readFileSync(filePath, "utf8").trim();
|
|
14
|
+
if (existing)
|
|
15
|
+
return existing;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
/* no file yet */
|
|
19
|
+
}
|
|
20
|
+
const secret = generateAuthSecret();
|
|
21
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
22
|
+
const tmpPath = `${filePath}.tmp`;
|
|
23
|
+
fs.writeFileSync(tmpPath, secret, { encoding: "utf8", mode: 0o600 });
|
|
24
|
+
fs.renameSync(tmpPath, filePath);
|
|
25
|
+
return secret;
|
|
26
|
+
};
|
|
27
|
+
export const signSessionToken = (secret, user) => {
|
|
28
|
+
const payload = {
|
|
29
|
+
sub: user,
|
|
30
|
+
exp: Date.now() + AUTH_COOKIE_MAX_AGE_SECONDS * 1000,
|
|
31
|
+
};
|
|
32
|
+
const data = Buffer.from(JSON.stringify(payload)).toString("base64url");
|
|
33
|
+
return `${data}.${sign(secret, data)}`;
|
|
34
|
+
};
|
|
35
|
+
export const verifySessionToken = (secret, token) => {
|
|
36
|
+
const dot = token.lastIndexOf(".");
|
|
37
|
+
if (dot <= 0)
|
|
38
|
+
return null;
|
|
39
|
+
const data = token.slice(0, dot);
|
|
40
|
+
const sig = token.slice(dot + 1);
|
|
41
|
+
const expected = sign(secret, data);
|
|
42
|
+
const sigBytes = Buffer.from(sig);
|
|
43
|
+
const expectedBytes = Buffer.from(expected);
|
|
44
|
+
if (sigBytes.length !== expectedBytes.length || !timingSafeEqual(sigBytes, expectedBytes)) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const payload = JSON.parse(Buffer.from(data, "base64url").toString("utf8"));
|
|
49
|
+
if (typeof payload?.sub !== "string" || typeof payload?.exp !== "number")
|
|
50
|
+
return null;
|
|
51
|
+
if (payload.exp < Date.now())
|
|
52
|
+
return null;
|
|
53
|
+
return payload.sub;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
// A cookie is `Secure` only when the browser's own origin is https — read from
|
|
60
|
+
// the `Origin` header the browser sends on the fetch (most reliable), with the
|
|
61
|
+
// request URL and `x-forwarded-proto` as fallbacks for a TLS-terminating proxy.
|
|
62
|
+
// On plain loopback HTTP we omit `Secure` (the cookie still works; loopback is
|
|
63
|
+
// the trusted surface) so the cookie is settable on every localterm surface.
|
|
64
|
+
const isSecureRequest = (context) => {
|
|
65
|
+
const origin = context.req.header("origin");
|
|
66
|
+
if (origin?.startsWith("https://"))
|
|
67
|
+
return true;
|
|
68
|
+
if (context.req.url.startsWith("https://"))
|
|
69
|
+
return true;
|
|
70
|
+
return context.req.header("x-forwarded-proto")?.includes("https") === true;
|
|
71
|
+
};
|
|
72
|
+
const cookieOptions = (context, maxAge) => ({
|
|
73
|
+
httpOnly: true,
|
|
74
|
+
sameSite: "Lax",
|
|
75
|
+
path: "/",
|
|
76
|
+
maxAge,
|
|
77
|
+
secure: isSecureRequest(context),
|
|
78
|
+
});
|
|
79
|
+
export const setSessionCookie = (context, secret, user) => {
|
|
80
|
+
setCookie(context, AUTH_COOKIE_NAME, signSessionToken(secret, user), cookieOptions(context, AUTH_COOKIE_MAX_AGE_SECONDS));
|
|
81
|
+
};
|
|
82
|
+
export const clearSessionCookie = (context) => {
|
|
83
|
+
setCookie(context, AUTH_COOKIE_NAME, "", cookieOptions(context, 0));
|
|
84
|
+
};
|
|
85
|
+
export const readSessionIdentity = (context, secret) => {
|
|
86
|
+
const token = getCookie(context, AUTH_COOKIE_NAME);
|
|
87
|
+
if (!token)
|
|
88
|
+
return null;
|
|
89
|
+
const sub = verifySessionToken(secret, token);
|
|
90
|
+
return sub ? { user: sub } : null;
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=session-cookie.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-cookie.js","sourceRoot":"","sources":["../../src/identity/session-cookie.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,2BAA2B,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAanG,MAAM,IAAI,GAAG,CAAC,MAAc,EAAE,IAAY,EAAU,EAAE,CACpD,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAEhE,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAW,EAAE,CAC7C,WAAW,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAEvD,6EAA6E;AAC7E,gFAAgF;AAChF,8EAA8E;AAC9E,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,QAAgB,EAAU,EAAE;IACjE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1D,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;IACD,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;IACpC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,GAAG,QAAQ,MAAM,CAAC;IAClC,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAc,EAAE,IAAY,EAAU,EAAE;IACvE,MAAM,OAAO,GAAmB;QAC9B,GAAG,EAAE,IAAI;QACT,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,2BAA2B,GAAG,IAAI;KACrD,CAAC;IACF,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACxE,OAAO,GAAG,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;AACzC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,MAAc,EAAE,KAAa,EAAiB,EAAE;IACjF,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACjC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,QAAQ,CAAC,MAAM,KAAK,aAAa,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC;QAC1F,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAmB,CAAC;QAC9F,IAAI,OAAO,OAAO,EAAE,GAAG,KAAK,QAAQ,IAAI,OAAO,OAAO,EAAE,GAAG,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACtF,IAAI,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;YAAE,OAAO,IAAI,CAAC;QAC1C,OAAO,OAAO,CAAC,GAAG,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,+EAA+E;AAC/E,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,6EAA6E;AAC7E,MAAM,eAAe,GAAG,CAAC,OAAgB,EAAW,EAAE;IACpD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAChD,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;AAC7E,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,OAAgB,EAAE,MAAc,EAAE,EAAE,CAAC,CAAC;IAC3D,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,KAAc;IACxB,IAAI,EAAE,GAAG;IACT,MAAM;IACN,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC;CACjC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAgB,EAAE,MAAc,EAAE,IAAY,EAAQ,EAAE;IACvF,SAAS,CACP,OAAO,EACP,gBAAgB,EAChB,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,EAC9B,aAAa,CAAC,OAAO,EAAE,2BAA2B,CAAC,CACpD,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAgB,EAAQ,EAAE;IAC3D,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAgB,EAAE,MAAc,EAAmB,EAAE;IACvF,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,GAAG,GAAG,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9C,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACpC,CAAC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Context } from "hono";
|
|
2
|
+
import type { Hono } from "hono";
|
|
3
|
+
export interface Identity {
|
|
4
|
+
user: string;
|
|
5
|
+
displayName?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface IdentityProvider {
|
|
8
|
+
readonly kind: string;
|
|
9
|
+
readonly denyUnauthenticated: boolean;
|
|
10
|
+
readonly operatorToken: string | null;
|
|
11
|
+
identify(context: Context, sourceIp: string | null): Identity | null;
|
|
12
|
+
routes?: () => Hono;
|
|
13
|
+
}
|
|
14
|
+
export type SessionOwner = string | null;
|
|
15
|
+
export interface HeaderIdentityConfig {
|
|
16
|
+
provider: "header";
|
|
17
|
+
header?: string;
|
|
18
|
+
trustedProxy?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface PasskeyIdentityConfig {
|
|
21
|
+
provider: "passkey";
|
|
22
|
+
rpName?: string;
|
|
23
|
+
registration?: "open" | "closed";
|
|
24
|
+
operatorToken?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface OidcIdentityConfig {
|
|
27
|
+
provider: "oidc";
|
|
28
|
+
issuer: string;
|
|
29
|
+
clientId: string;
|
|
30
|
+
clientSecret?: string;
|
|
31
|
+
claim?: string;
|
|
32
|
+
scope?: string;
|
|
33
|
+
operatorToken?: string;
|
|
34
|
+
}
|
|
35
|
+
export type IdentityConfig = HeaderIdentityConfig | PasskeyIdentityConfig | OidcIdentityConfig;
|
|
36
|
+
export type IdentityProviderKind = "header" | "passkey" | "oidc";
|
|
37
|
+
export interface IdentityProviderInfo {
|
|
38
|
+
provider: IdentityProviderKind | null;
|
|
39
|
+
registration?: "open" | "closed";
|
|
40
|
+
}
|
|
41
|
+
export interface AuthSession {
|
|
42
|
+
user: string | null;
|
|
43
|
+
}
|
|
44
|
+
export interface IdentityProviderDeps {
|
|
45
|
+
secret: string;
|
|
46
|
+
getOrigin: () => string | null;
|
|
47
|
+
stateDirectory: string;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/identity/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAKjC,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAcD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IAKtC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,CAAC;IAIrE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAOD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,IAAI,CAAC;AAEzC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAMhB,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAGjC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IAGjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IAEjB,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,cAAc,GAAG,oBAAoB,GAAG,qBAAqB,GAAG,kBAAkB,CAAC;AAM/F,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAEjE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAClC;AAKD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAMD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/identity/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
interface StoredUser {
|
|
2
|
+
username: string;
|
|
3
|
+
credentialIds: string[];
|
|
4
|
+
}
|
|
5
|
+
export declare class UserStore {
|
|
6
|
+
private readonly users;
|
|
7
|
+
private readonly filePath;
|
|
8
|
+
constructor(filePath: string);
|
|
9
|
+
get(username: string): StoredUser | null;
|
|
10
|
+
findOrCreate(username: string): StoredUser;
|
|
11
|
+
addCredential(username: string, credentialId: string): void;
|
|
12
|
+
private load;
|
|
13
|
+
private persist;
|
|
14
|
+
}
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=user-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-store.d.ts","sourceRoot":"","sources":["../../src/identity/user-store.ts"],"names":[],"mappings":"AAIA,UAAU,UAAU;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAeD,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,QAAQ,EAAE,MAAM;IAK5B,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAKxC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU;IAU1C,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAO3D,OAAO,CAAC,IAAI;IAyBZ,OAAO,CAAC,OAAO;CAUhB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
const usersFileSchema = z.object({
|
|
5
|
+
version: z.literal(1).optional(),
|
|
6
|
+
users: z.record(z.string(), z.object({ username: z.string(), credentialIds: z.array(z.string()) })),
|
|
7
|
+
});
|
|
8
|
+
// File-backed registry of passkey users (~/.localterm/users.json): username →
|
|
9
|
+
// the credential ids that authenticate them. Holds no key material (that's the
|
|
10
|
+
// credential store); this just answers "which credentials belong to this user"
|
|
11
|
+
// for registration exclude-lists and login allow-lists. Atomic tmp+rename write,
|
|
12
|
+
// graceful fallback to empty on a missing/corrupt file.
|
|
13
|
+
export class UserStore {
|
|
14
|
+
users = new Map();
|
|
15
|
+
filePath;
|
|
16
|
+
constructor(filePath) {
|
|
17
|
+
this.filePath = filePath;
|
|
18
|
+
this.load();
|
|
19
|
+
}
|
|
20
|
+
get(username) {
|
|
21
|
+
const user = this.users.get(username);
|
|
22
|
+
return user ? { ...user, credentialIds: [...user.credentialIds] } : null;
|
|
23
|
+
}
|
|
24
|
+
findOrCreate(username) {
|
|
25
|
+
let user = this.users.get(username);
|
|
26
|
+
if (!user) {
|
|
27
|
+
user = { username, credentialIds: [] };
|
|
28
|
+
this.users.set(username, user);
|
|
29
|
+
this.persist();
|
|
30
|
+
}
|
|
31
|
+
return { ...user, credentialIds: [...user.credentialIds] };
|
|
32
|
+
}
|
|
33
|
+
addCredential(username, credentialId) {
|
|
34
|
+
const user = this.users.get(username);
|
|
35
|
+
if (!user || user.credentialIds.includes(credentialId))
|
|
36
|
+
return;
|
|
37
|
+
user.credentialIds.push(credentialId);
|
|
38
|
+
this.persist();
|
|
39
|
+
}
|
|
40
|
+
load() {
|
|
41
|
+
let raw;
|
|
42
|
+
try {
|
|
43
|
+
raw = fs.readFileSync(this.filePath, "utf8");
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
let json;
|
|
49
|
+
try {
|
|
50
|
+
json = JSON.parse(raw);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
console.warn(`users file invalid; ignoring (${this.filePath})`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const parsed = usersFileSchema.safeParse(json);
|
|
57
|
+
if (!parsed.success) {
|
|
58
|
+
console.warn(`users file invalid; ignoring (${this.filePath})`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.users.clear();
|
|
62
|
+
for (const [username, user] of Object.entries(parsed.data.users)) {
|
|
63
|
+
this.users.set(username, { username: user.username, credentialIds: [...user.credentialIds] });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
persist() {
|
|
67
|
+
fs.mkdirSync(path.dirname(this.filePath), { recursive: true });
|
|
68
|
+
const payload = {
|
|
69
|
+
version: 1,
|
|
70
|
+
users: Object.fromEntries(this.users.entries()),
|
|
71
|
+
};
|
|
72
|
+
const tmpPath = `${this.filePath}.tmp`;
|
|
73
|
+
fs.writeFileSync(tmpPath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
|
74
|
+
fs.renameSync(tmpPath, this.filePath);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=user-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-store.js","sourceRoot":"","sources":["../../src/identity/user-store.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,12 +4,20 @@ import { type SnapshotProcesses } from "./caffeinate-process-match.js";
|
|
|
4
4
|
import type { DetectedBrowser } from "./cdp/detect-chromium.js";
|
|
5
5
|
import { type SecretBackend } from "./secret-backend.js";
|
|
6
6
|
import { type SnapshotListeners } from "./listening-ports.js";
|
|
7
|
+
import type { IdentityConfig } from "./identity/types.js";
|
|
7
8
|
import { SessionManager } from "./session-manager.js";
|
|
8
9
|
export interface ServerOptions {
|
|
9
10
|
port?: number;
|
|
10
11
|
host?: string;
|
|
11
12
|
staticRoot?: string | null;
|
|
12
13
|
stateDirectory?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Identity provider config — scopes the session registry per authenticated
|
|
16
|
+
* user. `null`/omitted = no provider (single-authority mode, byte-identical
|
|
17
|
+
* to no-auth). Overrides the config-file `identity` for tests/embedding; the
|
|
18
|
+
* provider is built once at start, so a change requires a restart.
|
|
19
|
+
*/
|
|
20
|
+
identity?: IdentityConfig | null;
|
|
13
21
|
/**
|
|
14
22
|
* The announced REMOTE surface origin — the URL the CLI resolved best-first
|
|
15
23
|
* (tailnet `https://<node>.ts.net`, portless `https://localterm.localhost`,
|
|
@@ -130,7 +138,8 @@ export type { CaffeinateControllerOptions, CaffeinateProcessHandle, } from "./ca
|
|
|
130
138
|
export type * from "./types.js";
|
|
131
139
|
export { DEFAULT_HOST, DEFAULT_PORT, WS_CLOSE_BACKPRESSURE } from "./constants.js";
|
|
132
140
|
export { isLoopbackHost, isPrivateHost, isAllowedSourceIp } from "./security.js";
|
|
133
|
-
export { healthSchema, cdpHealthSchema, daemonConfigSchema, updateDaemonConfigInputSchema, } from "./schemas.js";
|
|
141
|
+
export { healthSchema, cdpHealthSchema, daemonConfigSchema, identityConfigSchema, oidcConfigSchema, passkeyConfigSchema, updateDaemonConfigInputSchema, } from "./schemas.js";
|
|
142
|
+
export type { Identity, IdentityConfig, OidcIdentityConfig, PasskeyIdentityConfig, SessionOwner, } from "./identity/types.js";
|
|
134
143
|
export { createSessionInputSchema, sessionResponseSchema, updateSessionInputSchema, sessionInputSchema, sessionResizeSchema, execInputSchema, execOneShotInputSchema, execResultSchema, capturePaneResponseSchema, sessionsListResponseSchema, } from "./schemas.js";
|
|
135
144
|
export { createDefaultSecretBackend } from "./secret-backend.js";
|
|
136
145
|
export type { SecretBackend } from "./secret-backend.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAGlE,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|