From f04bd360f676cfe97c69b9fabec312315db2f52e Mon Sep 17 00:00:00 2001 From: Vitor Date: Wed, 16 Sep 2026 16:23:26 -0300 Subject: [PATCH 1/3] fix(storefront): Stop sending an expired login to the checkout app Returning customers whose stored token had expired were dropped on the "complete your registration" form as if they were new, and orders created duplicated customers. The legacy app.js trusts any `auth.id` on the `ecomPassportClient` cookie (no expiry check), requests `/customers/:id` with the dead token, gets 401 and logs out without leaving the form. vbeta-app now drops that cookie when the Cloud Commerce session is not authenticated and the cookie was written by it (level 3), keeping legacy e-mail + document identifications untouched. app.js then starts unidentified and receives the `login` event when the token is renewed, either before it loads (#785 wait) or later through `setSession`. Co-Authored-By: Claude Fable 5.1 --- .../storefront/src/lib/scripts/vbeta-app.ts | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/storefront/src/lib/scripts/vbeta-app.ts b/packages/storefront/src/lib/scripts/vbeta-app.ts index d01e1f6ae..396f69a15 100644 --- a/packages/storefront/src/lib/scripts/vbeta-app.ts +++ b/packages/storefront/src/lib/scripts/vbeta-app.ts @@ -263,6 +263,25 @@ if (!import.meta.env.SSR) { (window as any).ECOMCLIENT_API_MODULES = `${hostApiBaseUri}modules/`; const passportStorageKey = 'ecomPassportClient'; + // app.js trusts any `auth.id` on the passport cookie (no token expiry check) and + // requests `/customers/:id` with it: a stale token gets 401, then `logout()`, and + // the buyer is left on the "complete your registration" form as a new customer. + // Level 3 is set only from a Cloud Commerce session, so when that session is not + // authenticated the cookie holds an expired or logged out token: drop it, app.js + // starts unidentified and gets the `login` event once the token is renewed. + const clearStalePassportCookie = () => { + const cookieValue = document.cookie.split('; ') + .find((cookie) => cookie.startsWith(`${passportStorageKey}=`)) + ?.slice(passportStorageKey.length + 1); + if (!cookieValue) return; + try { + const { auth } = JSON.parse(decodeURIComponent(cookieValue)); + if (auth?.level !== 3) return; // legacy e-mail + doc identification, keep it + } catch { + // malformed, drop it anyway + } + setCookie(passportStorageKey, '', -1); + }; watch(isAuthenticated, async () => { const { ecomPassport } = window as Record; if (isAuthenticated.value) { @@ -281,8 +300,12 @@ if (!import.meta.env.SSR) { } else { setCookie(passportStorageKey, JSON.stringify(passportSession)); } - } else if (ecomPassport?.checkLogin()) { - ecomPassport.logout(); + } else if (ecomPassport) { + if (ecomPassport.checkLogin()) { + ecomPassport.logout(); + } + } else { + clearStalePassportCookie(); } }, { immediate: true, From 3ab14f8a07dbd02a7d781a5ed9e616af1ec54055 Mon Sep 17 00:00:00 2001 From: Leonardo Matos Date: Tue, 22 Sep 2026 17:24:38 -0300 Subject: [PATCH 2/3] fix(storefront): Checkout returns to identification when the login is rejected Update `@ecomplus/storefront-app` to 2.0.0-beta.229, which resets the account step when `GET /customers/:id` fails with a stale token (ecomplus/storefront#1314), the app-side complement of the stale passport cookie cleanup. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HYm5krXU4pnuPzynSUMQUg --- packages/storefront/src/lib/scripts/vbeta-app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/storefront/src/lib/scripts/vbeta-app.ts b/packages/storefront/src/lib/scripts/vbeta-app.ts index 396f69a15..8f52c1208 100644 --- a/packages/storefront/src/lib/scripts/vbeta-app.ts +++ b/packages/storefront/src/lib/scripts/vbeta-app.ts @@ -326,7 +326,7 @@ if (!import.meta.env.SSR) { const appScript = document.createElement('script'); appScript.src = src || (window as any)._appScriptSrc - || 'https://cdn.jsdelivr.net/npm/@ecomplus/storefront-app@2.0.0-beta.228/dist/lib/js/app.js'; + || 'https://cdn.jsdelivr.net/npm/@ecomplus/storefront-app@2.0.0-beta.229/dist/lib/js/app.js'; appScript.onload = () => { setTimeout(() => { watchAppRoutes(); From 04e012fca789e9b651b98aa3807bb357101b16a6 Mon Sep 17 00:00:00 2001 From: Leonardo Matos Date: Tue, 22 Sep 2026 17:26:43 -0300 Subject: [PATCH 3/3] chore(storefront): Trim comment on stale passport cookie cleanup Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HYm5krXU4pnuPzynSUMQUg --- packages/storefront/src/lib/scripts/vbeta-app.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/storefront/src/lib/scripts/vbeta-app.ts b/packages/storefront/src/lib/scripts/vbeta-app.ts index 8f52c1208..ee11bfb1b 100644 --- a/packages/storefront/src/lib/scripts/vbeta-app.ts +++ b/packages/storefront/src/lib/scripts/vbeta-app.ts @@ -263,12 +263,8 @@ if (!import.meta.env.SSR) { (window as any).ECOMCLIENT_API_MODULES = `${hostApiBaseUri}modules/`; const passportStorageKey = 'ecomPassportClient'; - // app.js trusts any `auth.id` on the passport cookie (no token expiry check) and - // requests `/customers/:id` with it: a stale token gets 401, then `logout()`, and - // the buyer is left on the "complete your registration" form as a new customer. - // Level 3 is set only from a Cloud Commerce session, so when that session is not - // authenticated the cookie holds an expired or logged out token: drop it, app.js - // starts unidentified and gets the `login` event once the token is renewed. + // app.js doesn't check token expiry: a stale level 3 (Cloud Commerce) cookie + // would 401 and leave the buyer as a new customer, so start it unidentified const clearStalePassportCookie = () => { const cookieValue = document.cookie.split('; ') .find((cookie) => cookie.startsWith(`${passportStorageKey}=`))