Merge pull request #599 from MODSetter/dev

hotfix(try): OAUTH_INVALID_STATE
This commit is contained in:
Rohan Verma 2025-12-19 12:50:10 -08:00 committed by GitHub
commit 50febcb4a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 38 additions and 19 deletions

View file

@ -1,7 +1,8 @@
from contextlib import asynccontextmanager
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi import Depends, FastAPI, HTTPException, Request, 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
@ -89,6 +90,28 @@ 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"])

View file

@ -9,24 +9,20 @@ export function GoogleLoginButton() {
const t = useTranslations("auth");
const handleGoogleLogin = () => {
// 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);
});
// 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`;
};
return (
<div className="relative w-full overflow-hidden">