session()->has('2fa.user_id')) { return redirect()->route('login'); } $user = User::find($request->session()->get('2fa.user_id')); if (! $user) { $request->session()->forget('2fa'); return redirect()->route('login'); } return view('auth.two-factor', [ 'maskedEmail' => $this->maskEmail($user->email), ]); } public function verify(Request $request): RedirectResponse { $request->validate(['pin' => ['required', 'string', 'digits:6']]); $userId = $request->session()->get('2fa.user_id'); $pinHash = $request->session()->get('2fa.pin_hash'); $expiresAt = $request->session()->get('2fa.expires_at'); if (! $userId || ! $pinHash) { return redirect()->route('login') ->withErrors(['email' => 'Session expirée. Veuillez vous reconnecter.']); } if (now()->timestamp > (int) $expiresAt) { $request->session()->forget('2fa'); return redirect()->route('login') ->withErrors(['email' => 'Le code PIN a expiré. Veuillez vous reconnecter.']); } if (! Hash::check($request->input('pin'), $pinHash)) { return back()->withErrors(['pin' => 'Code incorrect. Vérifiez votre e-mail et réessayez.']); } // PIN valide — authentifier l'utilisateur $user = User::findOrFail($userId); $intended = $request->session()->pull('2fa.intended', route('dashboard')); $request->session()->forget('2fa'); Auth::login($user); $request->session()->regenerate(); return redirect($intended); } public function resend(Request $request): RedirectResponse { $userId = $request->session()->get('2fa.user_id'); if (! $userId) { return redirect()->route('login'); } $user = User::find($userId); if (! $user) { return redirect()->route('login'); } $pin = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT); $request->session()->put([ '2fa.pin_hash' => Hash::make($pin), '2fa.expires_at' => now()->addMinutes(10)->timestamp, ]); try { Mail::to($user->email)->send(new TwoFactorPinMail($pin, $user->name)); } catch (\Exception $e) { return back()->withErrors(['pin' => "Impossible d'envoyer le code : " . $e->getMessage()]); } return back()->with('resent', true); } private function maskEmail(string $email): string { [$local, $domain] = explode('@', $email, 2); $visible = min(2, strlen($local)); $masked = substr($local, 0, $visible) . str_repeat('*', max(strlen($local) - $visible, 3)); return $masked . '@' . $domain; } }