From 0584c461906b7ad92773eb086f66f32c54b5a0f0 Mon Sep 17 00:00:00 2001 From: Mathis HERRIOT <197931332+0x485254@users.noreply.github.com> Date: Thu, 29 Jan 2026 13:49:54 +0100 Subject: [PATCH] feat: add 2FA prompt and OTP input to login flow - Integrated 2FA verification into the login process. - Added conditional rendering for OTP input. - Updated UI to support dynamic switching between login and 2FA views. - Introduced new state variables for managing 2FA logic. --- frontend/src/app/(auth)/login/page.tsx | 134 ++++++++++++++++++------- 1 file changed, 99 insertions(+), 35 deletions(-) diff --git a/frontend/src/app/(auth)/login/page.tsx b/frontend/src/app/(auth)/login/page.tsx index 42d5ca0..3a52b2d 100644 --- a/frontend/src/app/(auth)/login/page.tsx +++ b/frontend/src/app/(auth)/login/page.tsx @@ -24,6 +24,12 @@ import { FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; +import { + InputOTP, + InputOTPGroup, + InputOTPSeparator, + InputOTPSlot, +} from "@/components/ui/input-otp"; import { useAuth } from "@/providers/auth-provider"; const loginSchema = z.object({ @@ -36,8 +42,11 @@ const loginSchema = z.object({ type LoginFormValues = z.infer; export default function LoginPage() { - const { login } = useAuth(); + const { login, verify2fa } = useAuth(); const [loading, setLoading] = React.useState(false); + const [show2fa, setShow2fa] = React.useState(false); + const [userId, setUserId] = React.useState(null); + const [otpValue, setOtpValue] = React.useState(""); const form = useForm({ resolver: zodResolver(loginSchema), @@ -50,7 +59,11 @@ export default function LoginPage() { async function onSubmit(values: LoginFormValues) { setLoading(true); try { - await login(values.email, values.password); + const res = await login(values.email, values.password); + if (res.userId && res.message === "Please provide 2FA token") { + setUserId(res.userId); + setShow2fa(true); + } } catch (_error) { // Error is handled in useAuth via toast } finally { @@ -58,6 +71,20 @@ export default function LoginPage() { } } + async function onOtpSubmit(e: React.FormEvent) { + e.preventDefault(); + if (!userId || otpValue.length !== 6) return; + + setLoading(true); + try { + await verify2fa(userId, otpValue); + } catch (_error) { + // Error handled in useAuth + } finally { + setLoading(false); + } + } + return (
@@ -70,45 +97,82 @@ export default function LoginPage() { - Connexion + + {show2fa ? "Double Authentification" : "Connexion"} + - Entrez vos identifiants pour accéder à votre compte MemeGoat. + {show2fa + ? "Entrez le code à 6 chiffres de votre application d'authentification." + : "Entrez vos identifiants pour accéder à votre compte MemeGoat."} -
- - ( - - Email - - - - - - )} - /> - ( - - Mot de passe - - - - - - )} - /> - + - + ) : ( +
+ + ( + + Email + + + + + + )} + /> + ( + + Mot de passe + + + + + + )} + /> + + + + )}