Graphical PDS migrator for AT Protocol
at main 4.6 kB view raw
1import { useEffect, useState } from "preact/hooks"; 2import { IS_BROWSER } from "fresh/runtime"; 3 4/** 5 * The OAuth callback props. 6 * @type {OAuthCallbackProps} 7 */ 8interface OAuthCallbackProps { 9 error?: string; 10} 11 12/** 13 * The OAuth callback component. 14 * @param props - The OAuth callback props 15 * @returns The OAuth callback component 16 * @component 17 */ 18export default function OAuthCallback( 19 { error: initialError }: OAuthCallbackProps, 20) { 21 const [error, setError] = useState<string | null>(initialError || null); 22 const [message, setMessage] = useState<string>( 23 "Completing authentication...", 24 ); 25 26 useEffect(() => { 27 if (!IS_BROWSER) return; 28 29 console.log("OAuth callback page reached"); 30 setMessage("OAuth callback page reached. Checking authentication..."); 31 32 const checkAuth = async () => { 33 try { 34 // Check if there's an error in the URL 35 const params = new URLSearchParams(globalThis.location.search); 36 const errorParam = params.get("error"); 37 if (errorParam) { 38 console.error("Auth error detected in URL params:", errorParam); 39 setError(`Authentication failed: ${errorParam}`); 40 return; 41 } 42 43 // Give cookies a moment to be processed 44 await new Promise((resolve) => setTimeout(resolve, 1500)); // Increased delay 45 setMessage("Checking if we're authenticated..."); 46 47 // Check if we're authenticated by fetching current user 48 try { 49 const cookies = document.cookie 50 .split(";") 51 .map((c) => c.trim()) 52 .filter((c) => c.length > 0); 53 54 console.log("Current cookies:", cookies); 55 56 const response = await fetch("/api/me", { 57 credentials: "include", // Explicitly include credentials 58 headers: { 59 "Accept": "application/json", 60 }, 61 }); 62 63 if (!response.ok) { 64 console.error( 65 "Profile API error:", 66 response.status, 67 response.statusText, 68 ); 69 const text = await response.text(); 70 console.error("Response body:", text); 71 throw new Error(`API returned ${response.status}`); 72 } 73 74 const user = await response.json(); 75 console.log("Current user check result:", user); 76 77 if (user) { 78 console.log("Successfully authenticated", user); 79 setMessage("Authentication successful! Redirecting..."); 80 // Redirect to home after a short delay 81 setTimeout(() => { 82 globalThis.location.href = "/"; 83 }, 1000); 84 } else { 85 console.error("Auth check returned empty user object:", user); 86 setError("Authentication session not found - no user data"); 87 } 88 } catch (apiErr: unknown) { 89 console.error("API error during auth check:", apiErr); 90 setError( 91 `Failed to verify authentication: ${ 92 apiErr instanceof Error ? apiErr.message : "Unknown error" 93 }`, 94 ); 95 } 96 } catch (err: unknown) { 97 console.error("General error in OAuth callback:", err); 98 setError( 99 `Failed to complete authentication: ${ 100 err instanceof Error ? err.message : "Unknown error" 101 }`, 102 ); 103 } 104 }; 105 106 checkAuth(); 107 }, []); 108 109 return ( 110 <div class="flex items-center justify-center py-16"> 111 <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-8 max-w-md w-full text-center"> 112 {error 113 ? ( 114 <div> 115 <h2 class="text-2xl font-bold text-red-500 mb-4"> 116 Authentication Failed 117 </h2> 118 <p class="text-red-500 mb-6">{error}</p> 119 <a 120 href="/login" 121 class="px-4 py-2 bg-blue-500 dark:bg-blue-600 text-white rounded-md hover:bg-blue-600 dark:hover:bg-blue-700 transition-colors" 122 > 123 Try Again 124 </a> 125 </div> 126 ) 127 : ( 128 <div> 129 <h2 class="text-2xl font-bold text-gray-800 dark:text-gray-200 mb-4"> 130 Authentication in Progress 131 </h2> 132 <div class="flex justify-center mb-4"> 133 <div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 dark:border-blue-400"> 134 </div> 135 </div> 136 <p class="text-gray-600 dark:text-gray-400">{message}</p> 137 </div> 138 )} 139 </div> 140 </div> 141 ); 142}