clusev/app/Livewire/Auth/TwoFactorChallenge.php

71 lines
2.0 KiB
PHP

<?php
namespace App\Livewire\Auth;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Validation\ValidationException;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Validate;
use Livewire\Component;
use PragmaRX\Google2FAQRCode\Google2FA;
#[Layout('layouts.auth')]
#[Title('Bestätigung — Clusev')]
class TwoFactorChallenge extends Component
{
#[Validate('required|string')]
public string $code = '';
public function mount()
{
if (! session()->has('2fa.user')) {
return $this->redirect(route('login'), navigate: true);
}
}
public function verify()
{
$this->validate();
$key = 'two-factor:'.md5(session('2fa.user').'|'.request()->ip());
if (RateLimiter::tooManyAttempts($key, 5)) {
throw ValidationException::withMessages([
'code' => 'Zu viele Versuche. Bitte in '.RateLimiter::availableIn($key).' Sekunden erneut versuchen.',
]);
}
$user = User::find(session('2fa.user'));
if (! $user || ! $user->hasTwoFactorEnabled()) {
session()->forget(['2fa.user', '2fa.remember']);
throw ValidationException::withMessages(['code' => 'Sitzung abgelaufen. Bitte erneut anmelden.']);
}
$valid = (new Google2FA())->verifyKey($user->two_factor_secret, preg_replace('/\s+/', '', $this->code));
if (! $valid) {
RateLimiter::hit($key, 60);
throw ValidationException::withMessages(['code' => 'Ungültiger Code.']);
}
RateLimiter::clear($key);
$remember = (bool) session('2fa.remember');
session()->forget(['2fa.user', '2fa.remember']);
Auth::login($user, $remember);
session()->regenerate();
return $this->redirectIntended(route('dashboard'), navigate: true);
}
public function render()
{
return view('livewire.auth.two-factor-challenge');
}
}