From d14fe10ea7948a744dda38d10c90c0b3bc567f08 Mon Sep 17 00:00:00 2001 From: Zayden Jung Date: Fri, 15 May 2026 21:46:18 +0800 Subject: [PATCH] Google OAuthbase version --- .gitignore | 4 +++- auth.py | 29 ++++++++++++++++++----------- docker-compose.yml | 5 +++-- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 898e654..f89a9fa 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ wheels/ # Virtual environments .venv -.env \ No newline at end of file +.env + +*.json \ No newline at end of file diff --git a/auth.py b/auth.py index a930898..feaef5c 100644 --- a/auth.py +++ b/auth.py @@ -1,57 +1,64 @@ import httpx -from fastapi import APIRouter, Request +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") - -REDIRECT_URI = "http://localhost:8000/auth/callback" +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={REDIRECT_URI}" + f"&redirect_uri={GOOGLE_REDIRECT_URI}" f"&response_type=code" f"&scope=openid email profile" + f"&state={state}" ) - return RedirectResponse(url) + response = RedirectResponse(url) + response.set_cookie("oauth_state", state, httponly=True) + return response @router.get("/auth/callback") -async def auth_callback(code: str): +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: - # 1. 用 code 换 token token_res = await client.post( GOOGLE_TOKEN_URL, data={ "code": code, "client_id": GOOGLE_CLIENT_ID, "client_secret": GOOGLE_CLIENT_SECRET, - "redirect_uri": REDIRECT_URI, + "redirect_uri": GOOGLE_REDIRECT_URI, "grant_type": "authorization_code", }, ) + token_json = token_res.json() access_token = token_json["access_token"] - # 2. 获取用户信息 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"], diff --git a/docker-compose.yml b/docker-compose.yml index cbd7c28..9a32a86 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,8 +24,9 @@ services: - db environment: DATABASE_URL: postgresql://${SERVICE_USER_POSTGRESQL}:${SERVICE_PASSWORD_POSTGRESQL}@db:5432/roleplay - GOOGLE_CLIENT_ID: your_client_id - GOOGLE_CLIENT_SECRET: your_secret + GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID} + GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET} + GOOGLE_REDIRECT_URI: ${GOOGLE_REDIRECT_URI} ports: - "8000:8000"