From 7926eb74b4d1970ebf1ddd53616fda946d023d49 Mon Sep 17 00:00:00 2001 From: MarkLo Date: Sat, 13 Dec 2025 06:42:20 +0800 Subject: [PATCH] --- backend/app/api/auth.py | 7 ++++- .../app/api/auth/callback/google/route.ts | 28 +++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/backend/app/api/auth.py b/backend/app/api/auth.py index f9cdf4d6..1abdeb8f 100644 --- a/backend/app/api/auth.py +++ b/backend/app/api/auth.py @@ -2,6 +2,7 @@ Google OAuth authentication routes """ import os +import logging import httpx from datetime import datetime from typing import Optional @@ -13,6 +14,8 @@ from sqlalchemy import select from backend.app.db import get_db, User, UserSettings from backend.app.services.auth_utils import create_access_token +logger = logging.getLogger(__name__) + router = APIRouter(prefix="/api/auth", tags=["Authentication"]) # Google OAuth Configuration - read at request time for dynamic updates @@ -23,7 +26,9 @@ def get_google_client_secret(): return os.getenv("GOOGLE_CLIENT_SECRET", "") def get_frontend_url(): - return os.getenv("FRONTEND_URL", "http://localhost:3000") + url = os.getenv("FRONTEND_URL", "http://localhost:3000") + logger.info(f"FRONTEND_URL resolved to: {url}") + return url # Google OAuth URLs GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth" diff --git a/frontend/app/api/auth/callback/google/route.ts b/frontend/app/api/auth/callback/google/route.ts index 5404f83a..9d2ff892 100644 --- a/frontend/app/api/auth/callback/google/route.ts +++ b/frontend/app/api/auth/callback/google/route.ts @@ -4,27 +4,49 @@ */ import { NextRequest, NextResponse } from "next/server"; +// Get the proper base URL from request headers (handles Railway proxy) +function getBaseUrl(request: NextRequest): string { + // Try to get the forwarded host first (used by proxies like Railway) + const forwardedHost = request.headers.get("x-forwarded-host"); + const forwardedProto = request.headers.get("x-forwarded-proto") || "https"; + + if (forwardedHost) { + return `${forwardedProto}://${forwardedHost}`; + } + + // Fall back to host header + const host = request.headers.get("host"); + if (host && !host.startsWith("0.0.0.0") && !host.startsWith("localhost")) { + return `https://${host}`; + } + + // Last resort: use environment variable + return process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3000"; +} + export async function GET(request: NextRequest) { const searchParams = request.nextUrl.searchParams; const code = searchParams.get("code"); const error = searchParams.get("error"); + + const baseUrl = getBaseUrl(request); // Handle OAuth errors if (error) { return NextResponse.redirect( - new URL(`/auth/callback?error=${encodeURIComponent(error)}`, request.url) + new URL(`/auth/callback?error=${encodeURIComponent(error)}`, baseUrl) ); } // Redirect to callback page with code if (code) { return NextResponse.redirect( - new URL(`/auth/callback?code=${encodeURIComponent(code)}`, request.url) + new URL(`/auth/callback?code=${encodeURIComponent(code)}`, baseUrl) ); } // No code or error return NextResponse.redirect( - new URL("/auth/callback?error=no_code", request.url) + new URL("/auth/callback?error=no_code", baseUrl) ); }