'use client'; export const dynamic = 'force-dynamic'; import React, { useEffect, useState, useRef, Suspense } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; import { ProgressSpinner } from 'primereact/progressspinner'; function AuthCallbackContent() { const router = useRouter(); const searchParams = useSearchParams(); const [status, setStatus] = useState('Traitement de l\'authentification...'); // ✅ Protection contre les appels multiples const hasExchanged = useRef(false); const isProcessing = useRef(false); useEffect(() => { const handleAuthCallback = async () => { // ✅ Vérifier si l'échange a déjà été fait if (hasExchanged.current || isProcessing.current) { console.log('⏭️ Code exchange already attempted or in progress, skipping'); return; } // ✅ Marquer comme en cours de traitement isProcessing.current = true; try { const code = searchParams.get('code'); const state = searchParams.get('state'); const error = searchParams.get('error'); console.log('🔐 Starting OAuth callback handling...'); if (error) { console.error('❌ OAuth error:', error); setStatus(`Erreur d'authentification: ${error}`); hasExchanged.current = true; setTimeout(() => router.push('/auth/login'), 3000); return; } if (!code) { console.error('❌ No authorization code'); setStatus('Code d\'autorisation manquant'); hasExchanged.current = true; setTimeout(() => router.push('/auth/login'), 3000); return; } // ✅ Marquer comme échangé AVANT l'appel hasExchanged.current = true; console.log('✅ Authorization code received, exchanging for tokens...'); setStatus('Échange du code d\'autorisation...'); // Échanger le code contre des tokens const response = await fetch('/api/auth/token', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ code, state }), }); if (!response.ok) { const errorData = await response.json().catch(() => ({})); console.error('❌ Token exchange failed:', errorData); throw new Error(errorData.error || 'Échec de l\'échange de token'); } const result = await response.json(); console.log('✅ Token exchange successful'); setStatus('Authentification réussie, redirection...'); // Les tokens sont maintenant stockés dans des cookies HttpOnly côté serveur // Pas besoin de les stocker dans localStorage // ✅ Nettoyer l'URL avant redirection const cleanUrl = window.location.pathname; window.history.replaceState({}, document.title, cleanUrl); // Rediriger vers le dashboard après un court délai setTimeout(() => { console.log('✅ Redirecting to dashboard'); window.location.href = '/dashboard'; }, 500); } catch (error) { console.error('❌ Error during authentication processing:', error); setStatus('Erreur lors de l\'authentification'); // En cas d'erreur, permettre un nouvel essai après un délai setTimeout(() => { hasExchanged.current = false; isProcessing.current = false; router.push('/auth/login'); }, 3000); } }; handleAuthCallback(); }, []); // ✅ Tableau vide - s'exécute UNE SEULE FOIS au montage return (
{status}