From 48091b48eef6456b518915ee45197605100fae7e Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Tue, 26 May 2026 11:08:35 -0700 Subject: [PATCH] Fix legacy cookie mixing --- .../apps/implementations/client-app-impl.ts | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts b/packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts index 213ae0b56..c05b51925 100644 --- a/packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts +++ b/packages/template/src/lib/stack-app/apps/implementations/client-app-impl.ts @@ -1044,6 +1044,36 @@ export class _StackClientAppImplIncomplete { + let selected: { refreshToken: string, updatedAt: number | null } | null = null; + for (const [name, value] of Object.entries(cookies)) { + if (!prefixes.some(prefix => name.startsWith(prefix))) continue; + const parsed = this._parseStructuredRefreshCookie(value); + if (!parsed) continue; + const candidateUpdatedAt = parsed.updatedAt ?? Number.NEGATIVE_INFINITY; + const selectedUpdatedAt = selected?.updatedAt ?? Number.NEGATIVE_INFINITY; + if (!selected || candidateUpdatedAt > selectedUpdatedAt) { + selected = parsed; + } + } + return selected; + }; + + const currentStructuredCookie = getNewestStructuredCookie(currentStructuredPrefixes); + if (currentStructuredCookie) { + return { + refreshToken: currentStructuredCookie.refreshToken, + updatedAt: currentStructuredCookie.updatedAt ?? null, + }; + } + + // Legacy cookies are migration-only. Once a Hexclave cookie exists, it wins; + // otherwise an old SDK tab with an anonymous legacy cookie can sign a + // new-SDK tab out through the compatibility read. for (const name of legacyNames) { const value = cookies[name]; if (value) { @@ -1051,17 +1081,7 @@ export class _StackClientAppImplIncomplete name.startsWith(prefix))) continue; - const parsed = this._parseStructuredRefreshCookie(value); - if (!parsed) continue; - const candidateUpdatedAt = parsed.updatedAt ?? Number.NEGATIVE_INFINITY; - const selectedUpdatedAt = selected?.updatedAt ?? Number.NEGATIVE_INFINITY; - if (!selected || candidateUpdatedAt > selectedUpdatedAt) { - selected = parsed; - } - } + const selected = getNewestStructuredCookie(structuredPrefixes); if (!selected) { return { refreshToken: null, updatedAt: null };