diff --git a/apps/agui/app/account/page.tsx b/apps/agui/app/account/page.tsx index 4c7e890..c5827bf 100644 --- a/apps/agui/app/account/page.tsx +++ b/apps/agui/app/account/page.tsx @@ -100,8 +100,9 @@ function AccountPageContent() { const agentIdMatch = apiBaseUrl.match(/\/api\/([^\/]+)/); const agentId = agentIdMatch ? agentIdMatch[1] : (currentAgent?.agent_id || 'scout'); - // Use agent-specific callback URL for linking - const redirectUri = encodeURIComponent(`${window.location.origin}/oauth/${agentId}/${provider}/callback`); + // Same-origin path only (see login/page.tsx): the API host's nginx + // forwards /oauth/* back to this origin. + const redirectUri = encodeURIComponent(`/oauth/${agentId}/${provider}/callback`); // apiBaseUrl does NOT include /v1, so we need to add it const oauthUrl = `${apiBaseUrl}/v1/auth/oauth/${provider}/login`; diff --git a/apps/agui/app/login/page.tsx b/apps/agui/app/login/page.tsx index 2fce575..d1cfd30 100644 --- a/apps/agui/app/login/page.tsx +++ b/apps/agui/app/login/page.tsx @@ -91,8 +91,11 @@ export default function LoginPage() { const apiBaseUrl = process.env.NEXT_PUBLIC_SCOUT_API_URL || process.env.NEXT_PUBLIC_API_BASE_URL || window.location.origin; - // Use static HTML callback page - const callbackUrl = `${window.location.origin}/oauth-complete.html?marketing_opt_in=${marketingOptIn}`; + // The agent accepts only a same-origin PATH as its OAuth return (an + // absolute URL on another origin is refused as an open redirect). The + // browser therefore lands on the API host, whose nginx forwards + // /oauth-complete.html back to this origin with the one-time code. + const callbackUrl = `/oauth-complete.html?marketing_opt_in=${marketingOptIn}`; const redirectUri = encodeURIComponent(callbackUrl); // apiBaseUrl does NOT include /v1, so we need to add it const oauthUrl = `${apiBaseUrl}/v1/auth/oauth/${provider}/login`;