diff --git a/src/pages/Auth.tsx b/src/pages/Auth.tsx index e8f5f4b0..597fd703 100644 --- a/src/pages/Auth.tsx +++ b/src/pages/Auth.tsx @@ -37,6 +37,7 @@ export default function Auth() { const [signInCaptchaToken, setSignInCaptchaToken] = useState(null); const [signInCaptchaKey, setSignInCaptchaKey] = useState(0); const [mfaFactorId, setMfaFactorId] = useState(null); + const [mfaPendingEmail, setMfaPendingEmail] = useState(null); const emailParam = searchParams.get('email'); const messageParam = searchParams.get('message'); @@ -154,10 +155,17 @@ export default function Auth() { const totpFactor = factors?.totp?.find(f => f.status === 'verified'); if (totpFactor) { - // Show MFA challenge + // CRITICAL SECURITY FIX: IMMEDIATELY DESTROY THE AAL1 SESSION + // The user MUST NOT have any active session before completing MFA + console.log('[Auth] MFA required - destroying AAL1 session before challenge'); + await supabase.auth.signOut(); + + // Store email and factor ID in component state ONLY + // At this point, user has NO authenticated session + setMfaPendingEmail(formData.email); setMfaFactorId(totpFactor.id); setLoading(false); - return; // Stay on page, show MFA modal + return; // User has NO session - MFA modal will show } else { // MFA is required but no factor found - FORCE SIGN OUT for security console.error('[Auth] SECURITY: MFA required but no verified factor found'); @@ -245,35 +253,9 @@ export default function Auth() { }; const handleMfaCancel = async () => { - try { - // CRITICAL SECURITY: Log cancellation attempt - const { data: { session } } = await supabase.auth.getSession(); - if (session) { - try { - const { data: aalData } = await supabase.auth.mfa.getAuthenticatorAssuranceLevel(); - await supabase.rpc('log_admin_action', { - _admin_user_id: session.user.id, - _action: 'mfa_verification_cancelled', - _target_user_id: session.user.id, - _details: { - timestamp: new Date().toISOString(), - reason: 'user_cancelled_mfa_prompt', - aal_before_cancel: aalData?.currentLevel || 'aal1' - } - }); - } catch (logError) { - console.error('Failed to log MFA cancellation:', logError); - } - } - } catch (error) { - console.error('Error during MFA cancellation:', error); - } - - // CRITICAL SECURITY: User cannot bypass MFA if enrolled - // Cancelling MFA prompt MUST sign the user out - await supabase.auth.signOut(); - + // Clear state variables setMfaFactorId(null); + setMfaPendingEmail(null); setSignInCaptchaKey(prev => prev + 1); toast({