diff --git a/frontend/client/lib/api/auth.ts b/frontend/client/lib/api/auth.ts index 93315ce..1880062 100644 --- a/frontend/client/lib/api/auth.ts +++ b/frontend/client/lib/api/auth.ts @@ -21,8 +21,6 @@ export type RefreshTokenResponse = { refreshToken: string; }; -const baseURL = apiBaseUrl(); - export async function login(data: LoginRequest): Promise { const { data: res } = await apiClient.post("/api/v1/auth/login", data); return res; @@ -72,7 +70,7 @@ export async function changePassword( } export async function refreshToken(token: string): Promise { - const { data } = await axios.post(`${baseURL}/api/v1/auth/refresh`, { + const { data } = await axios.post(`${apiBaseUrl()}/api/v1/auth/refresh`, { refreshToken: token, }); return data; diff --git a/frontend/client/lib/api/client.ts b/frontend/client/lib/api/client.ts index f51d31c..bc0388c 100644 --- a/frontend/client/lib/api/client.ts +++ b/frontend/client/lib/api/client.ts @@ -14,15 +14,15 @@ export type ApiError = { type RetryableConfig = InternalAxiosRequestConfig & { _retry?: boolean }; -const baseURL = apiBaseUrl(); - export const apiClient: AxiosInstance = axios.create({ - baseURL, headers: { "Content-Type": "application/json" }, }); -// Attach access token from in-memory Zustand store on every request. +// Resolve the API base per-request + attach the access token. window.__ENV (runtime config) +// may not be populated at module-load on a hard page load (e.g. the OAuth callback), which +// would otherwise cache the localhost fallback and send requests to the wrong origin. apiClient.interceptors.request.use((config) => { + config.baseURL = apiBaseUrl(); const token = useAuthStore.getState().token; if (token) { config.headers.set("Authorization", `Bearer ${token}`); @@ -97,7 +97,7 @@ apiClient.interceptors.response.use( try { const { data } = await axios.post<{ accessToken: string; refreshToken: string }>( - `${baseURL}/api/v1/auth/refresh`, + `${apiBaseUrl()}/api/v1/auth/refresh`, { refreshToken }, ); setToken(data.accessToken); diff --git a/frontend/client/lib/auth/token.ts b/frontend/client/lib/auth/token.ts index 17179bb..ac5c033 100644 --- a/frontend/client/lib/auth/token.ts +++ b/frontend/client/lib/auth/token.ts @@ -55,8 +55,6 @@ function isExpiredSoon(token: string | null, bufferMs = 30_000): boolean { return exp * 1000 < Date.now() + bufferMs; } -const BASE_URL = apiBaseUrl(); - export async function getValidAccessToken(force = false): Promise { const token = getAccessToken(); // `force` refreshes even a still-valid token — used by the idle keep-alive timer so @@ -68,7 +66,7 @@ export async function getValidAccessToken(force = false): Promise const { refreshToken, setToken, setRefreshToken, logout } = useAuthStore.getState(); if (!refreshToken) { logout(); return null; } - const res = await fetch(`${BASE_URL}/api/v1/auth/refresh`, { + const res = await fetch(`${apiBaseUrl()}/api/v1/auth/refresh`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ refreshToken }),