@camstack/server 1.2.594 → 1.2.596
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/addon-root-inventory.js +50 -11
- package/dist/agent/addon-scan.js +44 -6
- package/dist/agent/agent-addon-runtime.js +8 -3
- package/dist/agent/agent-addon-updates.js +52 -12
- package/dist/agent/agent-cap-dispatch-service.js +5 -3
- package/dist/agent/agent-config.js +42 -7
- package/dist/agent/agent-deploy-swap.js +41 -5
- package/dist/agent/agent-group-runner.js +47 -8
- package/dist/agent/agent-http-auth.js +22 -10
- package/dist/agent/agent-http.js +113 -64
- package/dist/agent/agent-hub-addon-update.js +16 -10
- package/dist/agent/agent-hub-registration.js +7 -4
- package/dist/agent/agent-infra-capabilities.js +9 -5
- package/dist/agent/agent-json-file.js +42 -5
- package/dist/agent/agent-mesh-gate.js +8 -5
- package/dist/agent/agent-node-certificates.js +28 -25
- package/dist/agent/agent-pairing-local.js +47 -10
- package/dist/agent/agent-pairing-routes.js +20 -16
- package/dist/agent/agent-pairing-store.js +58 -18
- package/dist/agent/agent-reconnect.js +4 -1
- package/dist/agent/agent-service.js +71 -35
- package/dist/agent/agent-sniffing-listener.js +48 -11
- package/dist/agent/agent-undeploy.js +41 -5
- package/dist/agent/agent-update-routes.js +19 -14
- package/dist/agent/agent-update-service.js +80 -38
- package/dist/agent/apply-model-distribution.js +4 -1
- package/dist/agent/apply-stage-dev-uploads.js +9 -6
- package/dist/agent/derive-hub-url.js +8 -3
- package/dist/agent/fetch-bundle-from-hub.js +9 -6
- package/dist/agent/hubs-found.js +43 -6
- package/dist/agent/infra-boot-guard.js +4 -1
- package/dist/agent/infra-boot-plan.js +6 -2
- package/dist/agent/main.js +183 -148
- package/dist/agent/register-agent-cap-dispatch.js +6 -3
- package/dist/agent/serial-queue.js +7 -2
- package/dist/agent-status-page.js +4 -1
- package/dist/api/addon-upload.js +61 -22
- package/dist/api/agent-addon-delivery.js +11 -6
- package/dist/api/auth-whoami.js +4 -1
- package/dist/api/backup-download-pump.js +9 -5
- package/dist/api/backup-download.js +10 -7
- package/dist/api/core/addon-settings.router.js +19 -16
- package/dist/api/core/agent-pairing.router.js +79 -76
- package/dist/api/core/agents.router.js +24 -21
- package/dist/api/core/auth-admin-tokens.procedures.js +52 -48
- package/dist/api/core/auth-device-cert.procedures.js +67 -62
- package/dist/api/core/auth-limits.js +25 -16
- package/dist/api/core/auth-reauth.procedures.js +37 -32
- package/dist/api/core/auth-revoke-credentials.procedures.js +26 -22
- package/dist/api/core/auth-sessions.procedures.js +56 -52
- package/dist/api/core/auth.router.js +304 -300
- package/dist/api/core/cap-providers.js +121 -74
- package/dist/api/core/capabilities.router.js +37 -34
- package/dist/api/core/capability-preference-writes.js +17 -10
- package/dist/api/core/certificates.router.js +109 -106
- package/dist/api/core/cluster-nodes.router.js +18 -15
- package/dist/api/core/collection-preference.js +6 -2
- package/dist/api/core/event-bus-proxy.router.js +37 -34
- package/dist/api/core/failure-contributions.js +8 -4
- package/dist/api/core/hwaccel.router.js +20 -17
- package/dist/api/core/integration-secrets.js +12 -8
- package/dist/api/core/lifecycle-job-runner.js +49 -13
- package/dist/api/core/live-events.router.js +32 -29
- package/dist/api/core/load-contributions.js +8 -4
- package/dist/api/core/logging-settings.js +43 -30
- package/dist/api/core/logs.router.js +43 -40
- package/dist/api/core/notifications.router.js +18 -15
- package/dist/api/core/public-event-filter.js +8 -4
- package/dist/api/core/repl.router.js +21 -18
- package/dist/api/core/request-census-settings.js +16 -11
- package/dist/api/core/server-management.provider.js +4 -1
- package/dist/api/core/server-name.js +17 -9
- package/dist/api/core/site-location.js +24 -16
- package/dist/api/core/stream-probe.router.js +24 -21
- package/dist/api/core/system-events.router.js +26 -23
- package/dist/api/cors/cors-policy.js +29 -20
- package/dist/api/cors/register-cors-policy.js +14 -9
- package/dist/api/deploy-stage-registry.js +10 -6
- package/dist/api/dev-uploads-bundle.js +50 -12
- package/dist/api/health/adaptive-probe.routes.js +13 -9
- package/dist/api/health/health.routes.js +13 -8
- package/dist/api/hub-cluster-url.js +9 -3
- package/dist/api/model-distributor.js +50 -12
- package/dist/api/oauth2/consent-page.js +13 -10
- package/dist/api/oauth2/oauth2-routes.js +25 -17
- package/dist/api/oauth2/private-host.js +4 -1
- package/dist/api/server-upload-propagate.js +51 -15
- package/dist/api/server-upload.js +50 -13
- package/dist/api/sse-no-compression.js +4 -1
- package/dist/api/static/frame-policy.js +9 -4
- package/dist/api/static/precompressed-asset.js +57 -15
- package/dist/api/static/spa-mount.js +47 -8
- package/dist/api/static/spa-static.js +12 -5
- package/dist/api/tarball-manifest.js +44 -7
- package/dist/api/trpc/cap-mount-helpers.js +12 -7
- package/dist/api/trpc/cap-route-error-formatter.js +13 -10
- package/dist/api/trpc/cap-router-runtime.js +51 -40
- package/dist/api/trpc/client-ip.js +20 -9
- package/dist/api/trpc/core-cap-bridge.js +42 -32
- package/dist/api/trpc/device-collection-dispatch.js +27 -23
- package/dist/api/trpc/device-config-secret-redaction.js +40 -24
- package/dist/api/trpc/generated-cap-mounts.js +225 -219
- package/dist/api/trpc/generated-cap-routers.js +5167 -4852
- package/dist/api/trpc/http-request-census-hook.js +11 -8
- package/dist/api/trpc/http-request-census.js +41 -34
- package/dist/api/trpc/http-request-census.singleton.js +8 -4
- package/dist/api/trpc/localized-schema-paths.js +4 -1
- package/dist/api/trpc/principal-visibility.js +22 -14
- package/dist/api/trpc/remote-addon-update-grant.js +4 -1
- package/dist/api/trpc/scope-access.js +15 -10
- package/dist/api/trpc/server-provided-caps.js +7 -3
- package/dist/api/trpc/share-view-access.js +14 -6
- package/dist/api/trpc/trpc-error-device-tags.js +6 -3
- package/dist/api/trpc/trpc-error-principal.js +6 -2
- package/dist/api/trpc/trpc.context.js +25 -20
- package/dist/api/trpc/trpc.middleware.js +46 -38
- package/dist/api/trpc/trpc.router.js +99 -58
- package/dist/api/trpc/user-error.js +8 -5
- package/dist/api/trpc/ws-request-census.js +24 -17
- package/dist/api/trpc/ws-slow-consumer-guard.js +16 -11
- package/dist/api/upload-auth.js +9 -5
- package/dist/auth/addon-route-jwt-gate.js +7 -4
- package/dist/auth/addon-route-share-gate.js +12 -7
- package/dist/auth/app-confirm-page.js +22 -17
- package/dist/auth/app-confirm-routes.js +31 -26
- package/dist/auth/app-confirmations.js +44 -7
- package/dist/auth/app-page-shell.js +30 -17
- package/dist/auth/app-page-strings.js +17 -11
- package/dist/auth/app-passkey-page.js +21 -16
- package/dist/auth/app-passkey-routes.js +41 -37
- package/dist/auth/app-refused-route.js +18 -13
- package/dist/auth/auth-network-policy.js +15 -11
- package/dist/auth/auth-provider-gate.js +9 -4
- package/dist/auth/auth-rate-limit.js +7 -3
- package/dist/auth/client-address.js +9 -6
- package/dist/auth/device-enroll-proofs.js +43 -6
- package/dist/auth/external-link-intents.js +7 -3
- package/dist/auth/hub-sessions.js +12 -6
- package/dist/auth/native-link-completions.js +11 -7
- package/dist/auth/native-return.js +13 -9
- package/dist/auth/passkey-provider.js +32 -26
- package/dist/auth/second-factors.js +10 -6
- package/dist/auth/session-connections.js +12 -6
- package/dist/auth/session-cookie.js +23 -12
- package/dist/auth/session-lifetimes.js +12 -8
- package/dist/auth/session-mint.js +11 -4
- package/dist/auth/sso-finish-app.js +16 -13
- package/dist/auth/sso-finish-deps.js +27 -21
- package/dist/auth/sso-finish.js +38 -28
- package/dist/auth/sso-routes.js +25 -22
- package/dist/auth/used-bridge-ids.js +5 -1
- package/dist/boot/boot-config.js +55 -16
- package/dist/boot/init-sequence.js +4 -1
- package/dist/boot/integration-id-backfill.js +8 -3
- package/dist/boot/platform-keychain-key.js +42 -5
- package/dist/boot/post-boot.service.js +18 -14
- package/dist/boot/reconcile-lifecycle-jobs.js +6 -3
- package/dist/boot/retired-public-url-env.js +8 -4
- package/dist/bootstrap-packages.js +4 -1
- package/dist/closure-node-modules.js +38 -2
- package/dist/core/addon/addon-call-gateway.js +5 -1
- package/dist/core/addon/addon-package.service.js +123 -83
- package/dist/core/addon/addon-process-view.js +6 -2
- package/dist/core/addon/addon-realign-plan.js +4 -1
- package/dist/core/addon/addon-registry.service.js +187 -146
- package/dist/core/addon/addon-row-manifest.js +4 -1
- package/dist/core/addon/addon-search.service.js +7 -3
- package/dist/core/addon/addon-settings-provider.js +3 -1
- package/dist/core/addon/addon-uninstall.js +11 -4
- package/dist/core/addon/addon.tokens.js +5 -2
- package/dist/core/addon/device-meta-mirror.js +13 -8
- package/dist/core/addon/forked-custom-actions.js +11 -6
- package/dist/core/addon/integration-visibility.js +6 -3
- package/dist/core/addon/materialize-route-path.js +4 -1
- package/dist/core/addon/package-dir-utils.js +45 -8
- package/dist/core/addon/prune-misplaced-addons.js +43 -5
- package/dist/core/addon/runner-convergence.js +4 -1
- package/dist/core/addon/runner-serialization.js +4 -1
- package/dist/core/addon/runner-spawn-fanout.js +8 -3
- package/dist/core/addon/settings-door-wiring.js +8 -5
- package/dist/core/addon/single-flight-refresh.js +4 -1
- package/dist/core/addon-bridge/addon-bridge.service.js +44 -7
- package/dist/core/addon-pages/addon-pages.service.js +40 -3
- package/dist/core/addon-widgets/addon-widgets.service.js +42 -4
- package/dist/core/agent/agent-addon-backfill.js +17 -9
- package/dist/core/agent/agent-delivery-ledger.js +7 -3
- package/dist/core/agent/agent-liveness-event.js +6 -2
- package/dist/core/agent/agent-pairing-http.js +45 -41
- package/dist/core/agent/agent-registry.service.js +89 -50
- package/dist/core/agent/cluster-node-history-mirror.js +7 -3
- package/dist/core/agent/cluster-node-history-store.js +35 -31
- package/dist/core/agent/hub-agent-pairing.js +5 -1
- package/dist/core/agent/node-certificates-client.js +6 -3
- package/dist/core/agent/node-directory.js +4 -1
- package/dist/core/app-links/well-known-app-links.js +6 -2
- package/dist/core/auth/auth.service.js +8 -3
- package/dist/core/auth/handoff-code.service.js +49 -11
- package/dist/core/auth/record-kinds.js +19 -16
- package/dist/core/auth/share-token.service.js +79 -42
- package/dist/core/capability/capability.service.js +5 -1
- package/dist/core/config/config.schema.js +6 -1
- package/dist/core/config/config.service.js +6 -2
- package/dist/core/events/event-bus.service.js +7 -3
- package/dist/core/feature/feature.service.js +6 -2
- package/dist/core/lifecycle/lifecycle-runner.singleton.js +10 -5
- package/dist/core/lifecycle/lifecycle-state-machine.js +5 -1
- package/dist/core/logging/log-ring-buffer.js +5 -1
- package/dist/core/logging/logging.service.js +9 -5
- package/dist/core/logging/scoped-logger.js +5 -1
- package/dist/core/moleculer/agent-readiness-pull.js +4 -1
- package/dist/core/moleculer/agent-registration-request.js +7 -3
- package/dist/core/moleculer/cap-call-fn.js +7 -4
- package/dist/core/moleculer/cap-route-authority.js +8 -3
- package/dist/core/moleculer/hub-mesh-guard.js +9 -5
- package/dist/core/moleculer/moleculer.service.js +86 -79
- package/dist/core/network/network-quality.service.js +6 -2
- package/dist/core/notification/notification-wrapper.service.js +7 -3
- package/dist/core/notification/toast-wrapper.service.js +7 -3
- package/dist/core/provider/provider.tokens.js +4 -1
- package/dist/core/repl/repl-engine.service.js +8 -4
- package/dist/core/runner-health/runner-boot-check.js +15 -7
- package/dist/core/runner-health/update-preflight.js +14 -9
- package/dist/core/server-update/server-update.service.js +49 -12
- package/dist/core/server-update/system-apply-closure-patches.js +42 -6
- package/dist/core/server-update/system-ensure-prebuilds.js +6 -3
- package/dist/core/server-update/system-exec-npm.js +5 -2
- package/dist/core/storage/fs-storage-backend.js +5 -1
- package/dist/core/storage/storage-location-manager.js +5 -1
- package/dist/core/storage/storage.service.js +6 -2
- package/dist/core/streaming/ffmpeg-stream-info.js +8 -3
- package/dist/core/streaming/stream-probe.service.js +16 -12
- package/dist/core/streaming/ttl-cache.js +5 -1
- package/dist/core/topology/topology-emitter.service.js +23 -19
- package/dist/core/update-availability-emitter.js +7 -3
- package/dist/core/update-availability-store.js +45 -8
- package/dist/core/updates/agent-installed-packages.js +9 -5
- package/dist/core/updates/restart-marker.js +8 -3
- package/dist/core/updates/update-check-scheduler.js +18 -13
- package/dist/core/updates/wrapper-update-checker.js +7 -3
- package/dist/first-boot-addon-plan.js +6 -2
- package/dist/framework-nodepath.js +38 -2
- package/dist/i18n/request-lang.js +11 -7
- package/dist/launcher.js +65 -30
- package/dist/lifecycle-journal-path.js +38 -2
- package/dist/main.js +324 -286
- package/dist/manual-boot.js +156 -117
- package/dist/node-role.js +4 -1
- package/dist/package-inventory.js +48 -7
- package/dist/pending-restore.js +43 -7
- package/dist/single-copy-cleanup-runner.js +45 -9
- package/dist/single-copy-cleanup.js +15 -7
- package/dist/sqlite-restore.js +48 -9
- package/dist/starter.js +39 -4
- package/dist/ui-serving/lazy-ui-serving.js +39 -3
- package/package.json +7 -7
|
@@ -1,4 +1,40 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DeviceEnrollProofs = exports.DEVICE_ENROLL_PROOF_TTL_MS = void 0;
|
|
37
|
+
const types_1 = require("@camstack/types");
|
|
2
38
|
/**
|
|
3
39
|
* Step-up proofs for `auth.enrollSelf` (D855).
|
|
4
40
|
*
|
|
@@ -10,15 +46,15 @@ import { userError } from '@camstack/types';
|
|
|
10
46
|
* `device-enroll`, bound to the user, 5 minutes, single use, kept only as a
|
|
11
47
|
* hash. It replaces no session.
|
|
12
48
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
49
|
+
const crypto = __importStar(require("node:crypto"));
|
|
50
|
+
exports.DEVICE_ENROLL_PROOF_TTL_MS = 5 * 60_000;
|
|
15
51
|
const MAX_PENDING = 1_000;
|
|
16
52
|
function hash(proof) {
|
|
17
53
|
return crypto.createHash('sha256').update(proof).digest('hex');
|
|
18
54
|
}
|
|
19
55
|
/** How long a spent reauth token / claimed session is remembered (past the token's own 5 min). */
|
|
20
56
|
const SPENT_MEMORY_MS = 6 * 60_000;
|
|
21
|
-
|
|
57
|
+
class DeviceEnrollProofs {
|
|
22
58
|
now;
|
|
23
59
|
logger;
|
|
24
60
|
pending = new Map();
|
|
@@ -39,9 +75,9 @@ export class DeviceEnrollProofs {
|
|
|
39
75
|
mint(userId) {
|
|
40
76
|
this.prune();
|
|
41
77
|
if (this.pending.size >= MAX_PENDING)
|
|
42
|
-
throw userError('server.step-up-busy', undefined, 'Too many pending step-up proofs');
|
|
78
|
+
throw (0, types_1.userError)('server.step-up-busy', undefined, 'Too many pending step-up proofs');
|
|
43
79
|
const proof = `cdp_${crypto.randomBytes(32).toString('base64url')}`;
|
|
44
|
-
const expiresAt = this.now() + DEVICE_ENROLL_PROOF_TTL_MS;
|
|
80
|
+
const expiresAt = this.now() + exports.DEVICE_ENROLL_PROOF_TTL_MS;
|
|
45
81
|
this.pending.set(hash(proof), { userId, expiresAt });
|
|
46
82
|
return { proof, expiresAt };
|
|
47
83
|
}
|
|
@@ -110,3 +146,4 @@ export class DeviceEnrollProofs {
|
|
|
110
146
|
this.pending.delete(k);
|
|
111
147
|
}
|
|
112
148
|
}
|
|
149
|
+
exports.DeviceEnrollProofs = DeviceEnrollProofs;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExternalLinkIntents = void 0;
|
|
1
4
|
/**
|
|
2
5
|
* Pending "link this sign-in account" requests (D782).
|
|
3
6
|
*
|
|
@@ -12,12 +15,12 @@
|
|
|
12
15
|
* Hub-local and in memory on purpose: an intent lives minutes, and a hub
|
|
13
16
|
* restart mid-link costs the user one more click.
|
|
14
17
|
*/
|
|
15
|
-
|
|
18
|
+
const node_crypto_1 = require("node:crypto");
|
|
16
19
|
/** Long enough for an IdP login with a password manager; short enough to be useless later. */
|
|
17
20
|
const DEFAULT_TTL_MS = 10 * 60_000;
|
|
18
21
|
/** Bounded: a session minting intents in a loop cannot grow this without limit. */
|
|
19
22
|
const DEFAULT_MAX_ENTRIES = 1_000;
|
|
20
|
-
|
|
23
|
+
class ExternalLinkIntents {
|
|
21
24
|
intents = new Map();
|
|
22
25
|
now;
|
|
23
26
|
ttlMs;
|
|
@@ -35,7 +38,7 @@ export class ExternalLinkIntents {
|
|
|
35
38
|
break;
|
|
36
39
|
this.intents.delete(oldest.value);
|
|
37
40
|
}
|
|
38
|
-
const handle = `li_${randomBytes(24).toString('base64url')}`;
|
|
41
|
+
const handle = `li_${(0, node_crypto_1.randomBytes)(24).toString('base64url')}`;
|
|
39
42
|
this.intents.set(handle, {
|
|
40
43
|
userId,
|
|
41
44
|
provider,
|
|
@@ -66,3 +69,4 @@ export class ExternalLinkIntents {
|
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
}
|
|
72
|
+
exports.ExternalLinkIntents = ExternalLinkIntents;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.userManagementInternal = userManagementInternal;
|
|
4
|
+
exports.createSessionBacking = createSessionBacking;
|
|
5
|
+
exports.sessionBackingFrom = sessionBackingFrom;
|
|
6
|
+
exports.createSessionTokenCheck = createSessionTokenCheck;
|
|
1
7
|
/**
|
|
2
8
|
* The hub's two uses of the login-session table, which `local-auth` owns and
|
|
3
9
|
* reaches only through its hub-internal surface (`UserManagementInternal`):
|
|
@@ -10,12 +16,12 @@
|
|
|
10
16
|
* Both resolve `user-management` per call: a hub whose local-auth is not up
|
|
11
17
|
* mints nothing and accepts no session (fail closed).
|
|
12
18
|
*/
|
|
13
|
-
|
|
19
|
+
const system_1 = require("@camstack/system");
|
|
14
20
|
/** The hub-internal user-management surface right now, or `null`. */
|
|
15
|
-
|
|
16
|
-
return getUserManagementInternal(registry.getSingleton('user-management'));
|
|
21
|
+
function userManagementInternal(registry) {
|
|
22
|
+
return (0, system_1.getUserManagementInternal)(registry.getSingleton('user-management'));
|
|
17
23
|
}
|
|
18
|
-
|
|
24
|
+
function createSessionBacking(sessions, lifetimes) {
|
|
19
25
|
return {
|
|
20
26
|
open: async (input) => {
|
|
21
27
|
const { session, refreshToken } = await sessions.create({
|
|
@@ -37,7 +43,7 @@ export function createSessionBacking(sessions, lifetimes) {
|
|
|
37
43
|
};
|
|
38
44
|
}
|
|
39
45
|
/** The session backing behind `registry`'s user-management, or `null` while it is not up. */
|
|
40
|
-
|
|
46
|
+
function sessionBackingFrom(registry, lifetimes) {
|
|
41
47
|
return () => {
|
|
42
48
|
const internal = userManagementInternal(registry);
|
|
43
49
|
return internal === null ? null : createSessionBacking(internal.sessions, lifetimes);
|
|
@@ -50,7 +56,7 @@ export function sessionBackingFrom(registry, lifetimes) {
|
|
|
50
56
|
* release unless it was issued before the user's cutoff (logout everywhere,
|
|
51
57
|
* a password change, deletion).
|
|
52
58
|
*/
|
|
53
|
-
|
|
59
|
+
function createSessionTokenCheck(registry) {
|
|
54
60
|
return (payload) => {
|
|
55
61
|
const internal = userManagementInternal(registry);
|
|
56
62
|
if (internal === null)
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NativeLinkCompletions = exports.NATIVE_LINK_CODE_TTL_MS = exports.NATIVE_LINK_CODE_PREFIX = void 0;
|
|
1
4
|
/**
|
|
2
5
|
* Native-app account links waiting for the app to claim them (D801).
|
|
3
6
|
*
|
|
@@ -14,20 +17,20 @@
|
|
|
14
17
|
* outcome, and the store is bounded. In memory: a hub restart mid-link costs
|
|
15
18
|
* one more tap.
|
|
16
19
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
const node_crypto_1 = require("node:crypto");
|
|
21
|
+
exports.NATIVE_LINK_CODE_PREFIX = 'nlc_';
|
|
22
|
+
exports.NATIVE_LINK_CODE_TTL_MS = 60_000;
|
|
20
23
|
const MAX_PENDING = 1_000;
|
|
21
24
|
function hash(code) {
|
|
22
|
-
return createHash('sha256').update(code).digest('hex');
|
|
25
|
+
return (0, node_crypto_1.createHash)('sha256').update(code).digest('hex');
|
|
23
26
|
}
|
|
24
|
-
|
|
27
|
+
class NativeLinkCompletions {
|
|
25
28
|
pending = new Map();
|
|
26
29
|
now;
|
|
27
30
|
ttlMs;
|
|
28
31
|
constructor(opts = {}) {
|
|
29
32
|
this.now = opts.now ?? Date.now;
|
|
30
|
-
this.ttlMs = opts.ttlMs ?? NATIVE_LINK_CODE_TTL_MS;
|
|
33
|
+
this.ttlMs = opts.ttlMs ?? exports.NATIVE_LINK_CODE_TTL_MS;
|
|
31
34
|
}
|
|
32
35
|
/** Park a verified link; returns the raw one-time code. */
|
|
33
36
|
park(link) {
|
|
@@ -38,7 +41,7 @@ export class NativeLinkCompletions {
|
|
|
38
41
|
break;
|
|
39
42
|
this.pending.delete(oldest.value);
|
|
40
43
|
}
|
|
41
|
-
const code = `${NATIVE_LINK_CODE_PREFIX}${randomBytes(32).toString('base64url')}`;
|
|
44
|
+
const code = `${exports.NATIVE_LINK_CODE_PREFIX}${(0, node_crypto_1.randomBytes)(32).toString('base64url')}`;
|
|
42
45
|
this.pending.set(hash(code), { ...link, expiresAt: this.now() + this.ttlMs });
|
|
43
46
|
return code;
|
|
44
47
|
}
|
|
@@ -62,3 +65,4 @@ export class NativeLinkCompletions {
|
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
67
|
}
|
|
68
|
+
exports.NativeLinkCompletions = NativeLinkCompletions;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ssoReturnLocation = ssoReturnLocation;
|
|
4
|
+
exports.browserHandoffLocation = browserHandoffLocation;
|
|
1
5
|
/**
|
|
2
6
|
* Where the hub's auth routes send a browser, as `Location` values (D801).
|
|
3
7
|
*
|
|
@@ -7,23 +11,23 @@
|
|
|
7
11
|
* and must never be prefixed;
|
|
8
12
|
* - a browser handoff lands on the account page and nowhere else.
|
|
9
13
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return hasUrlScheme(location) ? location : `${mount}${location}`;
|
|
14
|
+
const types_1 = require("@camstack/types");
|
|
15
|
+
const sso_finish_js_1 = require("./sso-finish.js");
|
|
16
|
+
function ssoReturnLocation(mount, location) {
|
|
17
|
+
return (0, types_1.hasUrlScheme)(location) ? location : `${mount}${location}`;
|
|
14
18
|
}
|
|
15
19
|
/**
|
|
16
20
|
* The account page, signed in by a session in the FRAGMENT that admin-ui's
|
|
17
21
|
* auth boot consumes (`#token=…&next=…`, as an SSO login return). Without a
|
|
18
22
|
* session — unknown, used or expired code — the plain login page.
|
|
19
23
|
*/
|
|
20
|
-
|
|
24
|
+
function browserHandoffLocation(mount, session) {
|
|
21
25
|
if (session === null)
|
|
22
|
-
return `${mount}${SSO_LOGIN_PATH}`;
|
|
26
|
+
return `${mount}${sso_finish_js_1.SSO_LOGIN_PATH}`;
|
|
23
27
|
const fragment = new URLSearchParams({
|
|
24
|
-
...sessionFragmentParams(session),
|
|
25
|
-
next: SSO_PROFILE_PATH,
|
|
28
|
+
...(0, sso_finish_js_1.sessionFragmentParams)(session),
|
|
29
|
+
next: sso_finish_js_1.SSO_PROFILE_PATH,
|
|
26
30
|
provider: 'browser-handoff',
|
|
27
31
|
});
|
|
28
|
-
return `${mount}${SSO_LOGIN_PATH}#${fragment.toString()}`;
|
|
32
|
+
return `${mount}${sso_finish_js_1.SSO_LOGIN_PATH}#${fragment.toString()}`;
|
|
29
33
|
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SetSecondFactorPreferenceSchema = exports.SecondFactorPreferenceSchema = exports.RemovePasskeySchema = exports.FinishDiscoverableAuthenticationSchema = exports.FinishAuthenticationSchema = exports.FinishRegistrationSchema = exports.OptionsJsonSchema = void 0;
|
|
4
|
+
exports.resolvePasskeyProvider = resolvePasskeyProvider;
|
|
5
|
+
exports.userHasPasskey = userHasPasskey;
|
|
6
|
+
exports.passkeySecondFactorOptedIn = passkeySecondFactorOptedIn;
|
|
7
|
+
const types_1 = require("@camstack/types");
|
|
8
|
+
const zod_1 = require("zod");
|
|
3
9
|
// ── Passkey (user-passkeys cap) resolution ───────────────────────────
|
|
4
10
|
//
|
|
5
11
|
// Cap-agnostic: the passkey provider is resolved through the
|
|
@@ -12,19 +18,19 @@ import { z } from 'zod';
|
|
|
12
18
|
// The proxy is loosely typed (`Record<method, (params)=>Promise<unknown>>`);
|
|
13
19
|
// its outputs are narrowed through the cap's own Zod schemas rather than
|
|
14
20
|
// cast to the provider type (repo rule: no `as` on cross-boundary values).
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
success: z.literal(true),
|
|
18
|
-
credentialId: z.string(),
|
|
21
|
+
exports.OptionsJsonSchema = zod_1.z.object({ optionsJSON: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()) });
|
|
22
|
+
exports.FinishRegistrationSchema = zod_1.z.object({
|
|
23
|
+
success: zod_1.z.literal(true),
|
|
24
|
+
credentialId: zod_1.z.string(),
|
|
19
25
|
});
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
verified: z.boolean(),
|
|
23
|
-
userId: z.string().nullable(),
|
|
26
|
+
exports.FinishAuthenticationSchema = zod_1.z.object({ verified: zod_1.z.boolean() });
|
|
27
|
+
exports.FinishDiscoverableAuthenticationSchema = zod_1.z.object({
|
|
28
|
+
verified: zod_1.z.boolean(),
|
|
29
|
+
userId: zod_1.z.string().nullable(),
|
|
24
30
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
exports.RemovePasskeySchema = zod_1.z.object({ success: zod_1.z.literal(true) });
|
|
32
|
+
exports.SecondFactorPreferenceSchema = zod_1.z.object({ enabled: zod_1.z.boolean() });
|
|
33
|
+
exports.SetSecondFactorPreferenceSchema = zod_1.z.object({ success: zod_1.z.literal(true) });
|
|
28
34
|
function proxyPasskeyProvider(proxy) {
|
|
29
35
|
const call = async (method, params) => {
|
|
30
36
|
const fn = proxy[method];
|
|
@@ -33,19 +39,19 @@ function proxyPasskeyProvider(proxy) {
|
|
|
33
39
|
return fn(params);
|
|
34
40
|
};
|
|
35
41
|
return {
|
|
36
|
-
beginRegistration: async (input) => OptionsJsonSchema.parse(await call('beginRegistration', input)),
|
|
37
|
-
finishRegistration: async (input) => FinishRegistrationSchema.parse(await call('finishRegistration', input)),
|
|
38
|
-
beginAuthentication: async (input) => OptionsJsonSchema.parse(await call('beginAuthentication', input)),
|
|
39
|
-
finishAuthentication: async (input) => FinishAuthenticationSchema.parse(await call('finishAuthentication', input)),
|
|
40
|
-
beginDiscoverableAuthentication: async (input) => OptionsJsonSchema.parse(await call('beginDiscoverableAuthentication', input)),
|
|
41
|
-
finishDiscoverableAuthentication: async (input) => FinishDiscoverableAuthenticationSchema.parse(await call('finishDiscoverableAuthentication', input)),
|
|
42
|
-
listPasskeys: async (input) => z.array(PasskeySummarySchema).parse(await call('listPasskeys', input)),
|
|
43
|
-
removePasskey: async (input) => RemovePasskeySchema.parse(await call('removePasskey', input)),
|
|
44
|
-
getSecondFactorPreference: async (input) => SecondFactorPreferenceSchema.parse(await call('getSecondFactorPreference', input)),
|
|
45
|
-
setSecondFactorPreference: async (input) => SetSecondFactorPreferenceSchema.parse(await call('setSecondFactorPreference', input)),
|
|
42
|
+
beginRegistration: async (input) => exports.OptionsJsonSchema.parse(await call('beginRegistration', input)),
|
|
43
|
+
finishRegistration: async (input) => exports.FinishRegistrationSchema.parse(await call('finishRegistration', input)),
|
|
44
|
+
beginAuthentication: async (input) => exports.OptionsJsonSchema.parse(await call('beginAuthentication', input)),
|
|
45
|
+
finishAuthentication: async (input) => exports.FinishAuthenticationSchema.parse(await call('finishAuthentication', input)),
|
|
46
|
+
beginDiscoverableAuthentication: async (input) => exports.OptionsJsonSchema.parse(await call('beginDiscoverableAuthentication', input)),
|
|
47
|
+
finishDiscoverableAuthentication: async (input) => exports.FinishDiscoverableAuthenticationSchema.parse(await call('finishDiscoverableAuthentication', input)),
|
|
48
|
+
listPasskeys: async (input) => zod_1.z.array(types_1.PasskeySummarySchema).parse(await call('listPasskeys', input)),
|
|
49
|
+
removePasskey: async (input) => exports.RemovePasskeySchema.parse(await call('removePasskey', input)),
|
|
50
|
+
getSecondFactorPreference: async (input) => exports.SecondFactorPreferenceSchema.parse(await call('getSecondFactorPreference', input)),
|
|
51
|
+
setSecondFactorPreference: async (input) => exports.SetSecondFactorPreferenceSchema.parse(await call('setSecondFactorPreference', input)),
|
|
46
52
|
};
|
|
47
53
|
}
|
|
48
|
-
|
|
54
|
+
function resolvePasskeyProvider(registry, moleculer) {
|
|
49
55
|
const local = registry?.getCollection('user-passkeys')?.[0] ?? null;
|
|
50
56
|
if (local)
|
|
51
57
|
return local;
|
|
@@ -57,7 +63,7 @@ export function resolvePasskeyProvider(registry, moleculer) {
|
|
|
57
63
|
* missing provider or a transport hiccup degrades to `false` so the
|
|
58
64
|
* login flow is never blocked by passkey introspection.
|
|
59
65
|
*/
|
|
60
|
-
|
|
66
|
+
async function userHasPasskey(userId, provider) {
|
|
61
67
|
if (!provider)
|
|
62
68
|
return false;
|
|
63
69
|
try {
|
|
@@ -77,7 +83,7 @@ export async function userHasPasskey(userId, provider) {
|
|
|
77
83
|
* hiccup all read as `false` so the preference lookup can never lock a
|
|
78
84
|
* user out of the password flow.
|
|
79
85
|
*/
|
|
80
|
-
|
|
86
|
+
async function passkeySecondFactorOptedIn(userId, provider) {
|
|
81
87
|
if (!provider || typeof provider.getSecondFactorPreference !== 'function')
|
|
82
88
|
return false;
|
|
83
89
|
try {
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SecondFactorSchema = void 0;
|
|
4
|
+
exports.collectSecondFactors = collectSecondFactors;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const passkey_provider_js_1 = require("./passkey-provider.js");
|
|
7
|
+
exports.SecondFactorSchema = zod_1.z.enum(['totp', 'passkey']);
|
|
8
|
+
async function collectSecondFactors(deps, userId, primary) {
|
|
5
9
|
const totpStatus = deps.getTotpStatus ? await deps.getTotpStatus({ userId }) : { enabled: false };
|
|
6
10
|
const factors = [];
|
|
7
11
|
if (totpStatus.enabled)
|
|
8
12
|
factors.push('totp');
|
|
9
13
|
if (primary !== 'passkey') {
|
|
10
14
|
const provider = deps.passkeyProvider();
|
|
11
|
-
const enrolled = await userHasPasskey(userId, provider);
|
|
12
|
-
if (enrolled && (await passkeySecondFactorOptedIn(userId, provider))) {
|
|
15
|
+
const enrolled = await (0, passkey_provider_js_1.userHasPasskey)(userId, provider);
|
|
16
|
+
if (enrolled && (await (0, passkey_provider_js_1.passkeySecondFactorOptedIn)(userId, provider))) {
|
|
13
17
|
factors.push('passkey');
|
|
14
18
|
}
|
|
15
19
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* What a login session still HOLDS on the hub — its open WebSockets and its
|
|
3
4
|
* live media sessions — so that revoking the session ends them.
|
|
@@ -15,12 +16,16 @@
|
|
|
15
16
|
* the session (the WebRTC `closeSession`); recorded playback rides the same
|
|
16
17
|
* cap, so the same hold covers it.
|
|
17
18
|
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.SessionConnections = exports.SESSION_ENDED_CLOSE_REASON = exports.SESSION_ENDED_CLOSE_CODE = void 0;
|
|
21
|
+
exports.getSessionConnections = getSessionConnections;
|
|
22
|
+
exports.__resetSessionConnectionsForTests = __resetSessionConnectionsForTests;
|
|
18
23
|
/** WebSocket close code a client recognises as "the hub ended this session". */
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
exports.SESSION_ENDED_CLOSE_CODE = 4401;
|
|
25
|
+
exports.SESSION_ENDED_CLOSE_REASON = 'session-ended';
|
|
21
26
|
/** Bound on live media holds kept per login session (oldest dropped past it). */
|
|
22
27
|
const MAX_MEDIA_HOLDS_PER_SESSION = 256;
|
|
23
|
-
|
|
28
|
+
class SessionConnections {
|
|
24
29
|
sockets = new Set();
|
|
25
30
|
media = new Map();
|
|
26
31
|
logger = null;
|
|
@@ -72,7 +77,7 @@ export class SessionConnections {
|
|
|
72
77
|
continue;
|
|
73
78
|
this.sockets.delete(tracked);
|
|
74
79
|
try {
|
|
75
|
-
tracked.socket.close(SESSION_ENDED_CLOSE_CODE, SESSION_ENDED_CLOSE_REASON);
|
|
80
|
+
tracked.socket.close(exports.SESSION_ENDED_CLOSE_CODE, exports.SESSION_ENDED_CLOSE_REASON);
|
|
76
81
|
sockets += 1;
|
|
77
82
|
}
|
|
78
83
|
catch (error) {
|
|
@@ -118,13 +123,14 @@ export class SessionConnections {
|
|
|
118
123
|
}
|
|
119
124
|
}
|
|
120
125
|
}
|
|
126
|
+
exports.SessionConnections = SessionConnections;
|
|
121
127
|
let instance = null;
|
|
122
128
|
/** The process-wide registry (the WS factory, the WebRTC wrapper and the revoke listener share it). */
|
|
123
|
-
|
|
129
|
+
function getSessionConnections() {
|
|
124
130
|
instance ??= new SessionConnections();
|
|
125
131
|
return instance;
|
|
126
132
|
}
|
|
127
133
|
/** Test-only. */
|
|
128
|
-
|
|
134
|
+
function __resetSessionConnectionsForTests() {
|
|
129
135
|
instance = null;
|
|
130
136
|
}
|
|
@@ -1,10 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SESSION_COOKIE = void 0;
|
|
4
|
+
exports.buildSessionCookie = buildSessionCookie;
|
|
5
|
+
exports.clearSessionCookie = clearSessionCookie;
|
|
6
|
+
exports.readSessionCookieFromHeader = readSessionCookieFromHeader;
|
|
7
|
+
exports.shouldRedirectToLogin = shouldRedirectToLogin;
|
|
8
|
+
exports.loginRedirectUrl = loginRedirectUrl;
|
|
9
|
+
exports.isEmbedRedirectTarget = isEmbedRedirectTarget;
|
|
10
|
+
exports.isSessionGradeJwtPayload = isSessionGradeJwtPayload;
|
|
11
|
+
exports.sessionCookieIsSecure = sessionCookieIsSecure;
|
|
1
12
|
/** Browser session cookie carrying the hub JWT. Set by POST /api/auth/session
|
|
2
13
|
* after a tRPC login; read by the addon-route catch-all for `authenticated`
|
|
3
14
|
* routes hit by a plain browser navigation. */
|
|
4
|
-
|
|
5
|
-
|
|
15
|
+
exports.SESSION_COOKIE = 'camstack_session';
|
|
16
|
+
function buildSessionCookie(token, ttlSec, opts = {}) {
|
|
6
17
|
return {
|
|
7
|
-
name: SESSION_COOKIE,
|
|
18
|
+
name: exports.SESSION_COOKIE,
|
|
8
19
|
value: token,
|
|
9
20
|
options: {
|
|
10
21
|
httpOnly: true,
|
|
@@ -17,9 +28,9 @@ export function buildSessionCookie(token, ttlSec, opts = {}) {
|
|
|
17
28
|
},
|
|
18
29
|
};
|
|
19
30
|
}
|
|
20
|
-
|
|
31
|
+
function clearSessionCookie(opts = {}) {
|
|
21
32
|
return {
|
|
22
|
-
name: SESSION_COOKIE,
|
|
33
|
+
name: exports.SESSION_COOKIE,
|
|
23
34
|
value: '',
|
|
24
35
|
options: { httpOnly: true, sameSite: 'lax', secure: opts.secure ?? true, path: '/', maxAge: 0 },
|
|
25
36
|
};
|
|
@@ -30,7 +41,7 @@ export function clearSessionCookie(opts = {}) {
|
|
|
30
41
|
* so callers don't depend on `@fastify/cookie` decoration order. Returns
|
|
31
42
|
* `null` when the header is absent or carries no `camstack_session` pair.
|
|
32
43
|
*/
|
|
33
|
-
|
|
44
|
+
function readSessionCookieFromHeader(header) {
|
|
34
45
|
if (!header)
|
|
35
46
|
return null;
|
|
36
47
|
for (const pair of header.split(';')) {
|
|
@@ -38,7 +49,7 @@ export function readSessionCookieFromHeader(header) {
|
|
|
38
49
|
if (eq === -1)
|
|
39
50
|
continue;
|
|
40
51
|
const name = pair.slice(0, eq).trim();
|
|
41
|
-
if (name !== SESSION_COOKIE)
|
|
52
|
+
if (name !== exports.SESSION_COOKIE)
|
|
42
53
|
continue;
|
|
43
54
|
const raw = pair.slice(eq + 1).trim();
|
|
44
55
|
if (raw === '')
|
|
@@ -55,7 +66,7 @@ export function readSessionCookieFromHeader(header) {
|
|
|
55
66
|
/** A browser navigation we can bounce to the login page: a top-level GET
|
|
56
67
|
* that wants HTML. Anything else (API call, POST, non-HTML) keeps the
|
|
57
68
|
* 401 behavior so programmatic clients get a clean error. */
|
|
58
|
-
|
|
69
|
+
function shouldRedirectToLogin(method, accept) {
|
|
59
70
|
return method === 'GET' && typeof accept === 'string' && accept.includes('text/html');
|
|
60
71
|
}
|
|
61
72
|
/**
|
|
@@ -67,14 +78,14 @@ export function shouldRedirectToLogin(method, accept) {
|
|
|
67
78
|
* the SPA re-mounts it itself (`hubPath`) — so one value serves both the
|
|
68
79
|
* relayed and the direct case.
|
|
69
80
|
*/
|
|
70
|
-
|
|
81
|
+
function loginRedirectUrl(originalUrl, mountPrefix = null) {
|
|
71
82
|
return `${mountPrefix ?? ''}/login?next=${encodeURIComponent(originalUrl)}`;
|
|
72
83
|
}
|
|
73
84
|
/** Allowed redirect target for `GET /api/embed-auth`: a same-origin RELATIVE
|
|
74
85
|
* path to a stream-broker embed page. Defeats open-redirects — the endpoint
|
|
75
86
|
* sets the session cookie from a Bearer token, so the `next` must be safe to
|
|
76
87
|
* bounce to. Rejects absolute/protocol-relative URLs, backslashes, and `..`. */
|
|
77
|
-
|
|
88
|
+
function isEmbedRedirectTarget(next) {
|
|
78
89
|
if (!next.startsWith('/addon/stream-broker/embed/'))
|
|
79
90
|
return false;
|
|
80
91
|
if (next.includes('\\') || next.includes('://') || next.includes('..'))
|
|
@@ -89,7 +100,7 @@ export function isEmbedRedirectTarget(next) {
|
|
|
89
100
|
* password-only attacker skip the second factor on every cookie-gated
|
|
90
101
|
* surface. Shared by `POST /api/auth/session` and `auth.exchangeSession`.
|
|
91
102
|
*/
|
|
92
|
-
|
|
103
|
+
function isSessionGradeJwtPayload(payload) {
|
|
93
104
|
if (payload === null || typeof payload !== 'object')
|
|
94
105
|
return false;
|
|
95
106
|
const p = payload;
|
|
@@ -121,7 +132,7 @@ export function isSessionGradeJwtPayload(payload) {
|
|
|
121
132
|
* which is set by the proxy and by nothing else on a direct browser hit. A
|
|
122
133
|
* direct caller inventing the proto header alone changes nothing.
|
|
123
134
|
*/
|
|
124
|
-
|
|
135
|
+
function sessionCookieIsSecure(requestProtocol, headers, forwardedPrefixHeader) {
|
|
125
136
|
const secureLeg = requestProtocol === 'https';
|
|
126
137
|
if (!secureLeg)
|
|
127
138
|
return false;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_ACCESS_TOKEN_EXPIRY = exports.SESSION_LIFETIME_KEY = exports.ACCESS_TOKEN_EXPIRY_KEY = void 0;
|
|
4
|
+
exports.readSessionLifetimes = readSessionLifetimes;
|
|
1
5
|
/**
|
|
2
6
|
* The two lifetimes of a login (System → Authentication):
|
|
3
7
|
*
|
|
@@ -11,10 +15,10 @@
|
|
|
11
15
|
* applies to the next login or refresh. A value that does not parse falls
|
|
12
16
|
* back to the default — never to something longer.
|
|
13
17
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
const system_1 = require("@camstack/system");
|
|
19
|
+
exports.ACCESS_TOKEN_EXPIRY_KEY = 'auth.accessTokenExpiry';
|
|
20
|
+
exports.SESSION_LIFETIME_KEY = 'auth.tokenExpiry';
|
|
21
|
+
exports.DEFAULT_ACCESS_TOKEN_EXPIRY = '2h';
|
|
18
22
|
const DEFAULT_ACCESS_SEC = 2 * 3600;
|
|
19
23
|
const MIN_ACCESS_SEC = 5 * 60;
|
|
20
24
|
const MAX_ACCESS_SEC = 24 * 3600;
|
|
@@ -26,12 +30,12 @@ function safeRead(read, key) {
|
|
|
26
30
|
return undefined;
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
|
-
|
|
30
|
-
const session = parseTokenExpiry(safeRead(read, SESSION_LIFETIME_KEY));
|
|
31
|
-
const configuredAccess = safeRead(read, ACCESS_TOKEN_EXPIRY_KEY);
|
|
33
|
+
function readSessionLifetimes(read) {
|
|
34
|
+
const session = (0, system_1.parseTokenExpiry)(safeRead(read, exports.SESSION_LIFETIME_KEY));
|
|
35
|
+
const configuredAccess = safeRead(read, exports.ACCESS_TOKEN_EXPIRY_KEY);
|
|
32
36
|
const access = configuredAccess === undefined || configuredAccess === null || configuredAccess === ''
|
|
33
37
|
? null
|
|
34
|
-
: parseTokenExpiry(configuredAccess);
|
|
38
|
+
: (0, system_1.parseTokenExpiry)(configuredAccess);
|
|
35
39
|
const accessSec = access !== null && access.ok
|
|
36
40
|
? Math.min(MAX_ACCESS_SEC, Math.max(MIN_ACCESS_SEC, access.seconds))
|
|
37
41
|
: DEFAULT_ACCESS_SEC;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SessionRefreshRefusedError = exports.SessionDirectoryUnavailableError = exports.SessionUserGoneError = void 0;
|
|
4
|
+
exports.createSessionMinter = createSessionMinter;
|
|
1
5
|
/** The user a credential names is not in `user-management` (deleted, or never existed). */
|
|
2
|
-
|
|
6
|
+
class SessionUserGoneError extends Error {
|
|
3
7
|
userId;
|
|
4
8
|
constructor(userId) {
|
|
5
9
|
super('User no longer exists');
|
|
@@ -7,15 +11,17 @@ export class SessionUserGoneError extends Error {
|
|
|
7
11
|
this.name = 'SessionUserGoneError';
|
|
8
12
|
}
|
|
9
13
|
}
|
|
14
|
+
exports.SessionUserGoneError = SessionUserGoneError;
|
|
10
15
|
/** `user-management` is not registered: an infrastructure failure, never a 401. */
|
|
11
|
-
|
|
16
|
+
class SessionDirectoryUnavailableError extends Error {
|
|
12
17
|
constructor() {
|
|
13
18
|
super('Login unavailable — `user-management` capability not registered');
|
|
14
19
|
this.name = 'SessionDirectoryUnavailableError';
|
|
15
20
|
}
|
|
16
21
|
}
|
|
22
|
+
exports.SessionDirectoryUnavailableError = SessionDirectoryUnavailableError;
|
|
17
23
|
/** A refresh token that does not continue a live session. */
|
|
18
|
-
|
|
24
|
+
class SessionRefreshRefusedError extends Error {
|
|
19
25
|
reason;
|
|
20
26
|
constructor(reason) {
|
|
21
27
|
super('Session expired — sign in again');
|
|
@@ -23,7 +29,8 @@ export class SessionRefreshRefusedError extends Error {
|
|
|
23
29
|
this.name = 'SessionRefreshRefusedError';
|
|
24
30
|
}
|
|
25
31
|
}
|
|
26
|
-
|
|
32
|
+
exports.SessionRefreshRefusedError = SessionRefreshRefusedError;
|
|
33
|
+
function createSessionMinter(deps) {
|
|
27
34
|
const findUserOrNull = async (userId) => {
|
|
28
35
|
const directory = deps.directory();
|
|
29
36
|
if (!directory)
|