diff --git a/backend/apps/nine_router.py b/backend/apps/nine_router.py index d4497957..fd098bba 100644 --- a/backend/apps/nine_router.py +++ b/backend/apps/nine_router.py @@ -123,20 +123,12 @@ async def start_oauth(provider: str) -> dict: except Exception: pass - # Fall back to authorization_code flow - callback_url = f"http://localhost:{NINE_ROUTER_PORT}/api/oauth/{provider}/callback" - r = await client.get( - f"{NINE_ROUTER_API}/oauth/{provider}/authorize", - params={"redirect_uri": callback_url}, - ) - r.raise_for_status() - data = r.json() + # For authorization_code providers (Claude, Codex, Gemini), + # open 9Router's own dashboard page where the user can connect. + # 9Router handles the full OAuth flow (popup + callback) internally. return { - "flow": "authorization_code", - "auth_url": data.get("authUrl", ""), - "code_verifier": data.get("codeVerifier", ""), - "state": data.get("state", ""), - "redirect_uri": callback_url, + "flow": "dashboard_redirect", + "dashboard_url": f"http://localhost:{NINE_ROUTER_PORT}/dashboard/providers", } diff --git a/frontend/src/app/pages/Settings/Settings.tsx b/frontend/src/app/pages/Settings/Settings.tsx index 703007ef..9d4727ef 100644 --- a/frontend/src/app/pages/Settings/Settings.tsx +++ b/frontend/src/app/pages/Settings/Settings.tsx @@ -251,9 +251,10 @@ const SubscriptionCards: React.FC = () => { setPollTimer(timer); setTimeout(() => { clearInterval(timer); setConnecting(null); setUserCode(''); }, 300000); - } else if (data.flow === 'authorization_code') { - // Auth code flow (Claude, Codex, Gemini) — open browser, poll for connection - if (data.auth_url) window.open(data.auth_url, '_blank'); + } else if (data.flow === 'authorization_code' || data.flow === 'dashboard_redirect') { + // Auth code flow (Claude, Codex, Gemini) — open 9Router dashboard, poll for connection + const url = data.dashboard_url || data.auth_url; + if (url) window.open(url, '_blank'); // Poll the providers list until this provider appears as connected const timer = setInterval(async () => {