diff --git a/frontend/app/api/config/route.ts b/frontend/app/api/config/route.ts new file mode 100644 index 00000000..ee979ac3 --- /dev/null +++ b/frontend/app/api/config/route.ts @@ -0,0 +1,11 @@ +/** + * API route to expose public configuration + * This allows environment variables to be loaded at runtime instead of build time + */ +import { NextResponse } from "next/server"; + +export async function GET() { + return NextResponse.json({ + googleClientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || "", + }); +} diff --git a/frontend/components/auth/login-button.tsx b/frontend/components/auth/login-button.tsx index ca6a60fe..3b80b60a 100644 --- a/frontend/components/auth/login-button.tsx +++ b/frontend/components/auth/login-button.tsx @@ -53,7 +53,11 @@ export function LoginButton() { return ( - @@ -90,10 +94,15 @@ export function LoginButton() { } return ( - ); } diff --git a/frontend/contexts/auth-context.tsx b/frontend/contexts/auth-context.tsx index bcbd8a28..3bced31d 100644 --- a/frontend/contexts/auth-context.tsx +++ b/frontend/contexts/auth-context.tsx @@ -31,12 +31,6 @@ const AuthContext = createContext(undefined); // Token storage key const TOKEN_KEY = "tradingagents_auth_token"; -// Google OAuth client ID from environment -const GOOGLE_CLIENT_ID = process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || ""; - -// Backend URL -const BACKEND_URL = process.env.NEXT_PUBLIC_API_URL || ""; - /** * Auth Provider Component */ @@ -44,6 +38,19 @@ export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null); const [token, setToken] = useState(null); const [isLoading, setIsLoading] = useState(true); + const [googleClientId, setGoogleClientId] = useState(""); + + // Fetch Google Client ID from API (runtime) + useEffect(() => { + fetch("/api/config") + .then(res => res.json()) + .then(data => { + setGoogleClientId(data.googleClientId || ""); + }) + .catch(err => { + console.error("Failed to fetch config:", err); + }); + }, []); // Parse JWT token to get user info const parseToken = useCallback((token: string): User | null => { @@ -102,7 +109,7 @@ export function AuthProvider({ children }: { children: ReactNode }) { // Login - redirect to Google OAuth const login = useCallback(() => { - if (!GOOGLE_CLIENT_ID) { + if (!googleClientId) { console.error("Google Client ID not configured"); alert("Google 登入尚未設定。請聯繫管理員。"); return; @@ -113,7 +120,7 @@ export function AuthProvider({ children }: { children: ReactNode }) { const scope = "openid email profile"; const params = new URLSearchParams({ - client_id: GOOGLE_CLIENT_ID, + client_id: googleClientId, redirect_uri: redirectUri, response_type: "code", scope: scope, @@ -122,7 +129,7 @@ export function AuthProvider({ children }: { children: ReactNode }) { }); window.location.href = `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`; - }, []); + }, [googleClientId]); // Logout const logout = useCallback(() => {