diff --git a/surfsense_backend/app/app.py b/surfsense_backend/app/app.py index 3285b846d..8d525d659 100644 --- a/surfsense_backend/app/app.py +++ b/surfsense_backend/app/app.py @@ -1,8 +1,7 @@ from contextlib import asynccontextmanager -from fastapi import Depends, FastAPI, HTTPException, Request, status +from fastapi import Depends, FastAPI, HTTPException, status from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import RedirectResponse from sqlalchemy.ext.asyncio import AsyncSession from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware @@ -90,28 +89,6 @@ if config.AUTH_TYPE == "GOOGLE": ], # blocks OAuth registration when disabled ) - # Convenience endpoint for browser-based login: - # - FastAPI Users `/auth/google/authorize` returns JSON {authorization_url: ...} - # - In production, it's more reliable to do a top-level navigation that - # immediately redirects to Google (avoids cross-site XHR/CORS pitfalls). - from fastapi import Query - from fastapi_users.router.oauth import generate_state_token - - @app.get("/auth/google/start", include_in_schema=False) - async def google_oauth_start( - request: Request, scopes: list[str] = Query(None) - ) -> RedirectResponse: - base = (config.BACKEND_URL or str(request.base_url)).rstrip("/") - callback_url = f"{base}/auth/google/callback" - - state = generate_state_token({}, SECRET) - authorization_url = await google_oauth_client.get_authorization_url( - callback_url, - state, - scopes, - ) - return RedirectResponse(authorization_url, status_code=302) - app.include_router(crud_router, prefix="/api/v1", tags=["crud"]) diff --git a/surfsense_web/app/(home)/login/GoogleLoginButton.tsx b/surfsense_web/app/(home)/login/GoogleLoginButton.tsx index 012906b37..52d79d72b 100644 --- a/surfsense_web/app/(home)/login/GoogleLoginButton.tsx +++ b/surfsense_web/app/(home)/login/GoogleLoginButton.tsx @@ -9,20 +9,24 @@ export function GoogleLoginButton() { const t = useTranslations("auth"); const handleGoogleLogin = () => { - // IMPORTANT: - // FastAPI Users OAuth stores the "state" in a cookie. - // Doing a cross-origin fetch() (www.surfsense.com -> backend.ssbacktemp.xyz) - // will NOT persist Set-Cookie unless you use credentials + non-wildcard CORS. - // The simplest/most reliable approach is a top-level navigation to the backend - // authorize endpoint so the cookie is set as first-party. - const backendUrl = process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL; - if (!backendUrl) { - console.error("Missing NEXT_PUBLIC_FASTAPI_BACKEND_URL"); - return; - } - - // This endpoint performs a 302 to Google (more reliable than fetching JSON). - window.location.href = `${backendUrl}/auth/google/start`; + // Redirect to Google OAuth authorization URL + fetch(`${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/auth/google/authorize`) + .then((response) => { + if (!response.ok) { + throw new Error("Failed to get authorization URL"); + } + return response.json(); + }) + .then((data) => { + if (data.authorization_url) { + window.location.href = data.authorization_url; + } else { + console.error("No authorization URL received"); + } + }) + .catch((error) => { + console.error("Error during Google login:", error); + }); }; return (