feat: Implement MFA Challenge Support

This commit is contained in:
gpt-engineer-app[bot]
2025-10-14 13:39:05 +00:00
parent 3e520e1520
commit 121f7c533a
3 changed files with 198 additions and 3 deletions

View File

@@ -11,6 +11,7 @@ import { useToast } from '@/hooks/use-toast';
import { TurnstileCaptcha } from './TurnstileCaptcha';
import { notificationService } from '@/lib/notificationService';
import { useCaptchaBypass } from '@/hooks/useCaptchaBypass';
import { MFAChallenge } from './MFAChallenge';
interface AuthModalProps {
open: boolean;
@@ -27,6 +28,7 @@ export function AuthModal({ open, onOpenChange, defaultTab = 'signin' }: AuthMod
const [captchaKey, setCaptchaKey] = useState(0);
const [signInCaptchaToken, setSignInCaptchaToken] = useState<string | null>(null);
const [signInCaptchaKey, setSignInCaptchaKey] = useState(0);
const [mfaFactorId, setMfaFactorId] = useState<string | null>(null);
const [formData, setFormData] = useState({
email: '',
password: '',
@@ -71,8 +73,19 @@ export function AuthModal({ open, onOpenChange, defaultTab = 'signin' }: AuthMod
signInOptions.options = { captchaToken: tokenToUse };
}
const { error } = await supabase.auth.signInWithPassword(signInOptions);
const { data, error } = await supabase.auth.signInWithPassword(signInOptions);
if (error) throw error;
// Check if MFA is required (user exists but no session)
if (data.user && !data.session) {
const totpFactor = data.user.factors?.find(f => f.factor_type === 'totp' && f.status === 'verified');
if (totpFactor) {
setMfaFactorId(totpFactor.id);
setLoading(false);
return;
}
}
toast({
title: "Welcome back!",
@@ -95,6 +108,16 @@ export function AuthModal({ open, onOpenChange, defaultTab = 'signin' }: AuthMod
}
};
const handleMfaSuccess = () => {
setMfaFactorId(null);
onOpenChange(false);
};
const handleMfaCancel = () => {
setMfaFactorId(null);
setSignInCaptchaKey(prev => prev + 1);
};
const handleSignUp = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
@@ -261,7 +284,15 @@ export function AuthModal({ open, onOpenChange, defaultTab = 'signin' }: AuthMod
</TabsList>
<TabsContent value="signin" className="space-y-4 mt-4">
<form onSubmit={handleSignIn} className="space-y-4">
{mfaFactorId ? (
<MFAChallenge
factorId={mfaFactorId}
onSuccess={handleMfaSuccess}
onCancel={handleMfaCancel}
/>
) : (
<>
<form onSubmit={handleSignIn} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="modal-signin-email">Email</Label>
<div className="relative">
@@ -374,6 +405,8 @@ export function AuthModal({ open, onOpenChange, defaultTab = 'signin' }: AuthMod
</Button>
</div>
</div>
</>
)}
</TabsContent>
<TabsContent value="signup" className="space-y-3 sm:space-y-4 mt-4">