From 092c482ef884e7fd9d47b3424bbf0d5622991b53 Mon Sep 17 00:00:00 2001 From: bourgeoa Date: Fri, 7 Aug 2026 18:21:51 +0200 Subject: [PATCH 1/2] to avoid no-session error on localhost, add session restore timeout --- src/authn/SolidAuthnLogic.ts | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/authn/SolidAuthnLogic.ts b/src/authn/SolidAuthnLogic.ts index 6aa198c..60819a8 100644 --- a/src/authn/SolidAuthnLogic.ts +++ b/src/authn/SolidAuthnLogic.ts @@ -4,6 +4,29 @@ import * as debug from '../util/debug' import type { SessionWithLegacyEvents } from '../authSession/authSession' import type { AuthenticationContext, AuthnLogic } from '../types' +// Some auth clients (uvdsl worker-backed session) only settle restore() on +// a worker message; a missing/unreachable RefreshWorker asset makes it hang +// forever. This caps the wait so the login UI can never spin indefinitely. +const SESSION_RESTORE_TIMEOUT_MS = 5000 + +/** + * Await a session restore promise, but give up after + * SESSION_RESTORE_TIMEOUT_MS and resolve with undefined so callers can + * treat a stalled restore as "no previous session". + */ +async function withRestoreTimeout (promise: Promise | null): Promise { + if (promise === null) return undefined + let timer: ReturnType | undefined + const timeout = new Promise(resolve => { + timer = setTimeout(() => resolve(undefined), SESSION_RESTORE_TIMEOUT_MS) + }) + try { + return await Promise.race([promise, timeout]) + } finally { + if (timer !== undefined) clearTimeout(timer) + } +} + export class SolidAuthnLogic implements AuthnLogic { private session: SessionWithLegacyEvents private checkUserInFlight: Promise | null = null @@ -93,10 +116,19 @@ export class SolidAuthnLogic implements AuthnLogic { url: redirectUrl.href }) } else { + // uvdsl-style session (no handleIncomingRedirect): restore then handle redirect. + // + // The worker-backed session (WebWorkerSession) resolves restore() ONLY + // when the SharedWorker posts a message back. If the worker asset can't + // be fetched — local/dev servers that don't serve the RefreshWorker + // chunk at the resolved URL, wrong MIME type, CSP, or a worker that + // fails before `onconnect` — the promise never settles and the login + // UI would spin forever. Race it against a timeout and treat a stall + // as "no previous session" so the page can render the login button. + const wasActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId) if (typeof sessionAny?.restore === 'function') { - const wasActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId) try { - await sessionAny.restore() + await withRestoreTimeout(sessionAny.restore()) } catch (error) { const message = error instanceof Error ? error.message : String(error) if (!/no session to restore/i.test(message)) { From 38e8af554783a55bcd414855e3246d65b468d766 Mon Sep 17 00:00:00 2001 From: bourgeoa Date: Fri, 7 Aug 2026 18:30:38 +0200 Subject: [PATCH 2/2] 4.0.8-3 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index a4b2043..d10d75e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "solid-logic", - "version": "4.0.8-1", + "version": "4.0.8-3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "solid-logic", - "version": "4.0.8-1", + "version": "4.0.8-3", "license": "MIT", "dependencies": { "@uvdsl/solid-oidc-client-browser": "^0.2.3", diff --git a/package.json b/package.json index 83a11b2..ccb33cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "solid-logic", - "version": "4.0.8-2", + "version": "4.0.8-3", "description": "Core business logic of SolidOS", "main": "dist/index.cjs.js", "module": "dist/index.esm.js",