Skip to content

Commit fd23b13

Browse files
0xSolacewakesync
andauthored
fix(cloud/frontend): StewardProvider syncs steward-session cookie to api.elizacloud.ai (#7360)
* fix(cloud/frontend): use apiFetch for /api/auth/steward-session so cookie sets on api.elizacloud.ai Follow-up to #7358. setSessionCookie was still calling raw fetch("/api/auth/steward-session"), which goes same-origin to www.elizacloud.ai. The Worker sets steward-token + steward-authed cookies on the host the Set-Cookie response came from, so they end up host-only on www.elizacloud.ai. Subsequent apiFetch calls (e.g. /api/auth/cli-session/<id>/complete) now go cross-origin to api.elizacloud.ai (per #7358 SPA-direct behaviour). The host-only www cookie does not flow on that cross-origin request, the request 401s, and the CLI login screen deadlocks at "Generating API Key" until the 30s client timeout fires. Switch setSessionCookie to apiFetch so the cookie-setting POST also goes to api.elizacloud.ai. The Set-Cookie response is now scoped to the same host that all subsequent /api/* calls hit. Production deploy verified: /api/auth/cli-session/<id>/complete returns 200 with the cookie attached, login flow unblocks past "Generating API Key". Co-authored-by: wakesync <shadow@shad0w.xyz> * fix(cloud/frontend): StewardProvider syncs steward-session cookie to api.elizacloud.ai Follow-up to #7359. The login form's setSessionCookie was switched to apiFetch in #7359, but StewardProvider has its own auto-sync useEffect that POSTs the localStorage token to /api/auth/steward-session via raw fetch. That request still goes same-origin to www.elizacloud.ai so the Set-Cookie response is scoped host-only to www. Then when the /auth/cli-login page's completeCliLogin sends apiFetch to api.elizacloud.ai, the host-only www cookie does not flow on the cross-origin request. The CLI login spinner deadlocks at 'Generating API Key' until the 30s client timeout fires. Same root cause, second seam. Add a stewardSessionUrl helper that returns the absolute Workers origin (https://api.elizacloud.ai/api/auth/steward-session) when the SPA is running on a known elizacloud.ai host, and fall back to the relative same-origin path everywhere else (dev, preview, ad-hoc hosts). All four steward-session calls in StewardProvider (one POST sync, three DELETE wipes) now go through stewardSessionUrl with explicit credentials: 'include'. Cookies set on api.elizacloud.ai by the POST flow with subsequent apiFetch calls. Verified live on production deploy 60caf2a0: - www.elizacloud.ai/api/health -> 200 JSON - www.elizacloud.ai/steward/auth/providers -> 200 JSON - /auth/cli-login completes the spinner past 'Generating API Key' Co-authored-by: wakesync <shadow@shad0w.xyz> --------- Co-authored-by: wakesync <shadow@shad0w.xyz>
1 parent 5c405c9 commit fd23b13

1 file changed

Lines changed: 30 additions & 4 deletions

File tree

cloud/packages/lib/providers/StewardProvider.tsx

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,29 @@ import { StewardAuth, StewardClient } from "@stwd/sdk";
55
import { createContext, useEffect, useMemo, useRef } from "react";
66
import { resolveBrowserStewardApiUrl } from "@/lib/steward-url";
77

8+
// Resolve the absolute origin to use for /api/* calls in the browser. On
9+
// known elizacloud.ai hosts, bypass the same-origin Pages Functions proxy
10+
// and hit the Workers API directly so the steward-session cookie is set on
11+
// the same host that subsequent apiFetch / cli-login calls hit. Without
12+
// this, the cookie is set on www.elizacloud.ai while later requests go
13+
// cross-origin to api.elizacloud.ai and the host-only cookie does not
14+
// flow, deadlocking the CLI login spinner at "Generating API Key".
15+
const ELIZA_CLOUD_PROXIED_HOSTS = new Set([
16+
"elizacloud.ai",
17+
"www.elizacloud.ai",
18+
"dev.elizacloud.ai",
19+
]);
20+
const ELIZA_CLOUD_DIRECT_API = "https://api.elizacloud.ai";
21+
22+
function stewardSessionUrl(): string {
23+
if (typeof window === "undefined") return "/api/auth/steward-session";
24+
const host = window.location.hostname.toLowerCase();
25+
if (ELIZA_CLOUD_PROXIED_HOSTS.has(host)) {
26+
return `${ELIZA_CLOUD_DIRECT_API}/api/auth/steward-session`;
27+
}
28+
return "/api/auth/steward-session";
29+
}
30+
831
/**
932
* Steward authentication provider for Eliza Cloud.
1033
*
@@ -134,7 +157,7 @@ export function clearStaleStewardSession(): void {
134157
// ignore
135158
}
136159
// Server-side cookies (HttpOnly — JS can't touch them directly).
137-
fetch("/api/auth/steward-session", { method: "DELETE" }).catch(() => {});
160+
fetch(stewardSessionUrl(), { method: "DELETE", credentials: "include" }).catch(() => {});
138161
// Notify any in-tab listeners; the "storage" event covers cross-tab.
139162
try {
140163
window.dispatchEvent(new CustomEvent("steward-token-sync"));
@@ -175,7 +198,7 @@ function AuthTokenSync({ children }: { children: React.ReactNode }) {
175198
lastSyncedToken.current = null;
176199
lastSyncedRefreshToken.current = null;
177200
wasAuthenticated.current = false;
178-
fetch("/api/auth/steward-session", { method: "DELETE" }).catch(() => {});
201+
fetch(stewardSessionUrl(), { method: "DELETE", credentials: "include" }).catch(() => {});
179202
}
180203
return;
181204
}
@@ -192,8 +215,9 @@ function AuthTokenSync({ children }: { children: React.ReactNode }) {
192215
lastSyncedRefreshToken.current = refreshToken;
193216
wasAuthenticated.current = true;
194217

195-
fetch("/api/auth/steward-session", {
218+
fetch(stewardSessionUrl(), {
196219
method: "POST",
220+
credentials: "include",
197221
headers: { "Content-Type": "application/json" },
198222
body: JSON.stringify({ token, refreshToken }),
199223
})
@@ -266,7 +290,9 @@ function AuthTokenSync({ children }: { children: React.ReactNode }) {
266290
lastSyncedToken.current = null;
267291
lastSyncedRefreshToken.current = null;
268292
wasAuthenticated.current = false;
269-
fetch("/api/auth/steward-session", { method: "DELETE" }).catch(() => {});
293+
fetch(stewardSessionUrl(), { method: "DELETE", credentials: "include" }).catch(
294+
() => {},
295+
);
270296
}
271297
}
272298
} catch (err) {

0 commit comments

Comments
 (0)