From 972dcd335011fe127be57c30b179f17837708d56 Mon Sep 17 00:00:00 2001 From: David Susskind Date: Tue, 28 Jul 2026 16:48:12 +0300 Subject: [PATCH 1/2] fix(auth): carry app_id in redirectToLogin from foreign origins From a foreign origin (local dev, where appBaseUrl is absolute) the hosted login page cannot resolve the app by Host, so redirectToLogin's bare /login?from_url=... lands on the apex with no app identity and 404s. Reuse getLoginUrl so the absolute-appBaseUrl path carries app_id; the same-origin production path (appBaseUrl === '') stays byte-identical. Co-Authored-By: Claude Fable 5 --- src/modules/auth.ts | 8 ++++++-- tests/unit/auth.test.js | 6 +++--- tests/unit/client.test.js | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/modules/auth.ts b/src/modules/auth.ts index 13c35d78..afdb8d9b 100644 --- a/src/modules/auth.ts +++ b/src/modules/auth.ts @@ -6,6 +6,7 @@ import { ChangePasswordParams, ResetPasswordParams, } from "./auth.types"; +import { getLoginUrl } from "../utils/auth-utils.js"; function isInsideIframe(): boolean { if (typeof window === "undefined") return false; @@ -116,8 +117,11 @@ export function createAuthModule( ? new URL(nextUrl, window.location.origin).toString() : window.location.href; - // Build the login URL - const loginUrl = `${options.appBaseUrl}/login?from_url=${encodeURIComponent(redirectUrl)}`; + // A foreign origin (e.g. local dev) can't resolve the app by Host, so + // the login URL must carry the app id; same-origin keeps the bare path. + const loginUrl = options.appBaseUrl + ? getLoginUrl(redirectUrl, { serverUrl: options.appBaseUrl, appId }) + : `/login?from_url=${encodeURIComponent(redirectUrl)}`; // Redirect to the login page window.location.href = loginUrl; diff --git a/tests/unit/auth.test.js b/tests/unit/auth.test.js index c31f7a17..a96b2c67 100644 --- a/tests/unit/auth.test.js +++ b/tests/unit/auth.test.js @@ -165,7 +165,7 @@ describe('Auth Module', () => { // Verify the redirect URL was set correctly expect(mockLocation.href).toBe( - `${appBaseUrl}/login?from_url=${encodeURIComponent(nextUrl)}` + `${appBaseUrl}/login?from_url=${encodeURIComponent(nextUrl)}&app_id=${appId}` ); // Restore window @@ -185,7 +185,7 @@ describe('Auth Module', () => { // Verify the redirect URL uses current URL expect(mockLocation.href).toBe( - `${appBaseUrl}/login?from_url=${encodeURIComponent(currentUrl)}` + `${appBaseUrl}/login?from_url=${encodeURIComponent(currentUrl)}&app_id=${appId}` ); // Restore window @@ -212,7 +212,7 @@ describe('Auth Module', () => { // Verify the redirect URL uses the custom appBaseUrl expect(mockLocation.href).toBe( - `${customAppBaseUrl}/login?from_url=${encodeURIComponent(nextUrl)}` + `${customAppBaseUrl}/login?from_url=${encodeURIComponent(nextUrl)}&app_id=${appId}` ); // Restore window diff --git a/tests/unit/client.test.js b/tests/unit/client.test.js index 5ba2eba2..4fdd5ec3 100644 --- a/tests/unit/client.test.js +++ b/tests/unit/client.test.js @@ -98,7 +98,7 @@ describe('appBaseUrl Normalization', () => { // Verify the redirect URL uses the custom appBaseUrl expect(mockLocation.href).toBe( - `${customAppBaseUrl}/login?from_url=${encodeURIComponent(nextUrl)}` + `${customAppBaseUrl}/login?from_url=${encodeURIComponent(nextUrl)}&app_id=test-app-id` ); // Restore window From 93d6e3f73bc6c6ab70ff61078a7721dd62b4be33 Mon Sep 17 00:00:00 2001 From: David Susskind Date: Wed, 29 Jul 2026 10:06:38 +0300 Subject: [PATCH 2/2] test(auth): lock in from_url encoding for nextUrl with a query string Co-Authored-By: Claude Fable 5 --- tests/unit/auth.test.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/unit/auth.test.js b/tests/unit/auth.test.js index a96b2c67..26f1a876 100644 --- a/tests/unit/auth.test.js +++ b/tests/unit/auth.test.js @@ -219,6 +219,23 @@ describe('Auth Module', () => { global.window = originalWindow; }); + test('should preserve a query string in nextUrl through from_url encoding', () => { + const originalWindow = global.window; + const mockLocation = { href: '' }; + global.window = { + location: mockLocation + }; + + const nextUrl = 'https://example.com/dashboard?tab=x&page=2'; + base44.auth.redirectToLogin(nextUrl); + + expect(mockLocation.href).toBe( + `${appBaseUrl}/login?from_url=${encodeURIComponent(nextUrl)}&app_id=${appId}` + ); + + global.window = originalWindow; + }); + test('should use relative URL for login redirect when appBaseUrl is not provided', () => { // Create a client without appBaseUrl const clientWithoutAppBaseUrl = createClient({