"use client"; import { ArrowLeft, CheckCircle, Loader2, XCircle } from "lucide-react"; import { useRouter, useSearchParams } from "next/navigation"; import { Suspense, useEffect, useState } from "react"; import AnimatedProcessingIcon from "@/components/icons/animated-processing-icon"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { useAuth } from "@/contexts/auth-context"; function AuthCallbackContent() { const router = useRouter(); const searchParams = useSearchParams(); const { refreshAuth } = useAuth(); const [status, setStatus] = useState<"processing" | "success" | "error">( "processing", ); const [error, setError] = useState(null); const [purpose, setPurpose] = useState("app_auth"); useEffect(() => { const code = searchParams.get("code"); const callbackKey = `callback_processed_${code}`; // Prevent double execution across component remounts if (sessionStorage.getItem(callbackKey)) { return; } sessionStorage.setItem(callbackKey, "true"); const handleCallback = async () => { try { // Get parameters from URL const state = searchParams.get("state"); const errorParam = searchParams.get("error"); // Get stored auth info const connectorId = localStorage.getItem("connecting_connector_id"); const storedConnectorType = localStorage.getItem( "connecting_connector_type", ); const authPurpose = localStorage.getItem("auth_purpose"); // Determine purpose - default to app_auth for login, data_source for connectors const detectedPurpose = authPurpose || (storedConnectorType?.includes("drive") ? "data_source" : "app_auth"); setPurpose(detectedPurpose); // Debug logging console.log("OAuth Callback Debug:", { urlParams: { code: !!code, state: !!state, error: errorParam }, localStorage: { connectorId, storedConnectorType, authPurpose }, detectedPurpose, fullUrl: window.location.href, }); // Use state parameter as connection_id if localStorage is missing const finalConnectorId = connectorId || state; if (errorParam) { throw new Error(`OAuth error: ${errorParam}`); } if (!code || !state || !finalConnectorId) { console.error("Missing OAuth callback parameters:", { code: !!code, state: !!state, finalConnectorId: !!finalConnectorId, }); throw new Error("Missing required parameters for OAuth callback"); } // Send callback data to backend const response = await fetch("/api/auth/callback", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ connection_id: finalConnectorId, authorization_code: code, state: state, }), }); const result = await response.json(); if (response.ok) { setStatus("success"); if (result.purpose === "app_auth" || detectedPurpose === "app_auth") { // App authentication - refresh auth context and redirect to home/original page await refreshAuth(); // Get redirect URL from login page const redirectTo = searchParams.get("redirect") || "/chat"; // Clean up localStorage localStorage.removeItem("connecting_connector_id"); localStorage.removeItem("connecting_connector_type"); localStorage.removeItem("auth_purpose"); // Redirect to the original page or home setTimeout(() => { router.push(redirectTo); }, 2000); } else { // Connector authentication - redirect to connectors page // Clean up localStorage localStorage.removeItem("connecting_connector_id"); localStorage.removeItem("connecting_connector_type"); localStorage.removeItem("auth_purpose"); // Redirect to settings page with success indicator setTimeout(() => { router.push("/settings?oauth_success=true"); }, 2000); } } else { throw new Error(result.error || "Authentication failed"); } } catch (err) { console.error("OAuth callback error:", err); setError(err instanceof Error ? err.message : "Unknown error occurred"); setStatus("error"); // Clean up localStorage on error too localStorage.removeItem("connecting_connector_id"); localStorage.removeItem("connecting_connector_type"); localStorage.removeItem("auth_purpose"); } }; handleCallback(); }, [searchParams, router, refreshAuth]); // Dynamic UI content based on purpose const isAppAuth = purpose === "app_auth"; const getTitle = () => { if (status === "processing") { return isAppAuth ? "Signing you in..." : "Connecting..."; } if (status === "success") { return isAppAuth ? "Welcome to OpenRAG!" : "Connection Successful!"; } if (status === "error") { return isAppAuth ? "Sign In Failed" : "Connection Failed"; } }; const getDescription = () => { if (status === "processing") { return isAppAuth ? "Please wait while we complete your sign in..." : "Please wait while we complete the connection..."; } if (status === "success") { return "You will be redirected shortly."; } if (status === "error") { return isAppAuth ? "There was an issue signing you in." : "There was an issue with the connection."; } }; return (
{status === "processing" && ( <> {getTitle()} )} {status === "success" && ( <> {getTitle()} )} {status === "error" && ( <> {getTitle()} )} {getDescription()} {status === "error" && (

{error}

)} {status === "success" && (

{isAppAuth ? "Redirecting you to the app..." : "Redirecting to settings..."}

)}
); } export default function AuthCallbackPage() { return ( Loading... Please wait while we process your request... } > ); }