diff --git a/frontend/src/components/two-factor-setup.tsx b/frontend/src/components/two-factor-setup.tsx new file mode 100644 index 0000000..21671b8 --- /dev/null +++ b/frontend/src/components/two-factor-setup.tsx @@ -0,0 +1,213 @@ +"use client"; + +import { useState } from "react"; +import { toast } from "sonner"; +import { Shield, ShieldCheck, ShieldAlert, Loader2 } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { + InputOTP, + InputOTPGroup, + InputOTPSeparator, + InputOTPSlot, +} from "@/components/ui/input-otp"; +import { AuthService } from "@/services/auth.service"; +import { useAuth } from "@/providers/auth-provider"; + +export function TwoFactorSetup() { + const { user, refreshUser } = useAuth(); + const [step, setStep] = useState<"idle" | "setup" | "verify">("idle"); + const [qrCode, setQrCode] = useState(null); + const [secret, setSecret] = useState(null); + const [otpValue, setOtpValue] = useState(""); + const [isLoading, setIsLoading] = useState(false); + + const handleSetup = async () => { + setIsLoading(true); + try { + const data = await AuthService.setup2fa(); + setQrCode(data.qrCodeUrl); + setSecret(data.secret); + setStep("setup"); + } catch (error) { + toast.error("Erreur lors de la configuration de la 2FA."); + } finally { + setIsLoading(false); + } + }; + + const handleEnable = async () => { + if (otpValue.length !== 6) return; + setIsLoading(true); + try { + await AuthService.enable2fa(otpValue); + toast.success("Double authentification activée !"); + await refreshUser(); + setStep("idle"); + setOtpValue(""); + } catch (error) { + toast.error("Code invalide. Veuillez réessayer."); + } finally { + setIsLoading(false); + } + }; + + const handleDisable = async () => { + if (otpValue.length !== 6) return; + setIsLoading(true); + try { + await AuthService.disable2fa(otpValue); + toast.success("Double authentification désactivée."); + await refreshUser(); + setStep("idle"); + setOtpValue(""); + } catch (error) { + toast.error("Code invalide. Veuillez réessayer."); + } finally { + setIsLoading(false); + } + }; + + // Note: We need a way to know if 2FA is enabled. + // Assuming user object might have twoFactorEnabled property or similar. + // For now, let's assume it's on the user object (we might need to add it to the type). + const isEnabled = (user as any)?.twoFactorEnabled; + + if (step === "idle") { + return ( + + +
+ + Double Authentification (2FA) +
+ + Ajoutez une couche de sécurité supplémentaire à votre compte en utilisant une application d'authentification. + +
+ +
+ {isEnabled ? ( + <> +
+ +
+
+

La 2FA est activée

+

Votre compte est protégé par un code temporaire.

+
+ + + ) : ( + <> +
+ +
+
+

La 2FA n'est pas activée

+

Activez la 2FA pour mieux protéger votre compte.

+
+ + + )} +
+
+
+ ); + } + + if (step === "setup") { + return ( + + + Configurer la 2FA + + Scannez le QR Code ci-dessous avec votre application d'authentification (Google Authenticator, Authy, etc.). + + + + {qrCode && ( +
+ QR Code 2FA +
+ )} +
+

Ou entrez ce code manuellement :

+ + {secret} + +
+
+

Entrez le code à 6 chiffres pour confirmer :

+ + + + + + + + + + + + + +
+
+ + + + +
+ ); + } + + if (step === "verify") { + return ( + + + Désactiver la 2FA + + Veuillez entrer le code de votre application pour désactiver la double authentification. + + + + + + + + + + + + + + + + + + + + + + + ); + } + + return null; +}