diff --git a/src/utils/axios-client.ts b/src/utils/axios-client.ts index 5a542ad..3c9e9d1 100644 --- a/src/utils/axios-client.ts +++ b/src/utils/axios-client.ts @@ -177,10 +177,10 @@ export function createAxiosClient({ client.interceptors.request.use((config) => { if (typeof window !== "undefined") { config.headers.set("X-Origin-URL", window.location.href); - // On unauthenticated clients, attach a stable anonymous visitor id so the - // backend can support anonymous agent access (conversation grouping + - // ownership). Authenticated clients are identified by their token instead. - if (!token) { + // On unauthenticated requests, attach a stable anonymous visitor id so the + // backend can support anonymous agent access (conversation grouping + ownership). + // Authenticated requests are identified by their Authorization header instead. + if (!config.headers.get("Authorization")) { config.headers.set("X-Base44-Anonymous-Id", getAnalyticsSessionId()); } } diff --git a/tests/unit/anonymous-visitor-header.test.ts b/tests/unit/anonymous-visitor-header.test.ts index b362608..689767f 100644 --- a/tests/unit/anonymous-visitor-header.test.ts +++ b/tests/unit/anonymous-visitor-header.test.ts @@ -31,8 +31,18 @@ afterEach(() => { vi.unstubAllGlobals(); }); -async function captureRequestHeaders(token?: string) { +async function captureRequestHeaders( + token?: string, + { tokenSetAfterConstruction }: { tokenSetAfterConstruction?: string } = {} +) { const client = createAxiosClient({ baseURL: "https://api", token }); + // Mirrors the common browser path: auth.setToken() applies the Authorization + // header on the client's defaults after the client has already been built. + if (tokenSetAfterConstruction) { + client.defaults.headers.common[ + "Authorization" + ] = `Bearer ${tokenSetAfterConstruction}`; + } let captured: any; client.defaults.adapter = async (config) => { captured = config; @@ -63,4 +73,12 @@ describe("anonymous visitor header", () => { expect(headers.get("X-Base44-Anonymous-Id")).toBeFalsy(); expect(headers.get("Authorization")).toBe("Bearer a-real-token"); }); + + test("token set after construction (browser setToken path) omits the anonymous header", async () => { + const headers = await captureRequestHeaders(undefined, { + tokenSetAfterConstruction: "a-real-token", + }); + expect(headers.get("Authorization")).toBe("Bearer a-real-token"); + expect(headers.get("X-Base44-Anonymous-Id")).toBeFalsy(); + }); });