import httpx from fastapi import APIRouter, Request, HTTPException from fastapi.responses import RedirectResponse import os import secrets router = APIRouter() GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID") GOOGLE_CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET") GOOGLE_REDIRECT_URI = os.getenv("GOOGLE_REDIRECT_URI") GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth" GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token" GOOGLE_USERINFO_URL = "https://www.googleapis.com/oauth2/v2/userinfo" @router.get("/login/google") def login_google(): state = secrets.token_urlsafe(16) url = ( f"{GOOGLE_AUTH_URL}" f"?client_id={GOOGLE_CLIENT_ID}" f"&redirect_uri={GOOGLE_REDIRECT_URI}" f"&response_type=code" f"&scope=openid email profile" f"&state={state}" ) response = RedirectResponse(url) response.set_cookie("oauth_state", state, httponly=True) return response @router.get("/auth/callback") async def auth_callback(request: Request, code: str, state: str): cookie_state = request.cookies.get("oauth_state") if not cookie_state or cookie_state != state: raise HTTPException(status_code=400, detail="Invalid state") async with httpx.AsyncClient() as client: token_res = await client.post( GOOGLE_TOKEN_URL, data={ "code": code, "client_id": GOOGLE_CLIENT_ID, "client_secret": GOOGLE_CLIENT_SECRET, "redirect_uri": GOOGLE_REDIRECT_URI, "grant_type": "authorization_code", }, ) token_json = token_res.json() access_token = token_json["access_token"] user_res = await client.get( GOOGLE_USERINFO_URL, headers={"Authorization": f"Bearer {access_token}"}, ) user_info = user_res.json() return { "email": user_info["email"], "name": user_info["name"], "picture": user_info["picture"], }