diff --git a/app/Livewire/Auth/ForgotPassword.php b/app/Livewire/Auth/ForgotPassword.php
index 5f249cb..7b6422a 100644
--- a/app/Livewire/Auth/ForgotPassword.php
+++ b/app/Livewire/Auth/ForgotPassword.php
@@ -65,7 +65,8 @@ class ForgotPassword extends Component
$ok = $user
&& $user->hasTwoFactorEnabled()
- && ((new Google2FA)->verifyKey($user->two_factor_secret, $clean) || $user->useRecoveryCode($this->code));
+ && (($user->hasTotp() && (new Google2FA)->verifyKey($user->two_factor_secret, $clean))
+ || $user->useRecoveryCode($this->code));
if (! $ok) {
RateLimiter::hit($key, 60);
diff --git a/lang/de/auth.php b/lang/de/auth.php
index 2f97319..9d56823 100644
--- a/lang/de/auth.php
+++ b/lang/de/auth.php
@@ -101,6 +101,7 @@ return [
'reset_done' => 'Passwort geändert. Bitte neu anmelden.',
'reset_link_sent' => 'Falls die E-Mail existiert, wurde ein Reset-Link versendet.',
'reset_token_invalid' => 'Reset-Link ungültig oder abgelaufen.',
+ 'reset_no_2fa_note' => 'Ohne 2FA ist die Wiederherstellung nur per E-Mail-Link (falls SMTP konfiguriert) oder über den Befehl clusev:reset-admin möglich.',
// ── WebAuthn / Security-Keys ─────────────────────────────────────────
'webauthn_login' => 'Mit Security-Key anmelden',
diff --git a/lang/en/auth.php b/lang/en/auth.php
index 9248f68..16008f6 100644
--- a/lang/en/auth.php
+++ b/lang/en/auth.php
@@ -101,6 +101,7 @@ return [
'reset_done' => 'Password changed. Please sign in again.',
'reset_link_sent' => 'If the email exists, a reset link has been sent.',
'reset_token_invalid' => 'Reset link is invalid or expired.',
+ 'reset_no_2fa_note' => 'Without 2FA, recovery is only possible via the email link (if SMTP is configured) or the clusev:reset-admin command.',
// ── WebAuthn / security keys ─────────────────────────────────────────
'webauthn_login' => 'Sign in with a security key',
diff --git a/resources/views/livewire/auth/forgot-password.blade.php b/resources/views/livewire/auth/forgot-password.blade.php
index 789c32e..2dc1443 100644
--- a/resources/views/livewire/auth/forgot-password.blade.php
+++ b/resources/views/livewire/auth/forgot-password.blade.php
@@ -41,5 +41,7 @@
{{ __('auth.reset_no_2fa_note') }}
+ {{ __('auth.back_to_login') }} diff --git a/tests/Feature/ForgotPasswordKeyOnlyTest.php b/tests/Feature/ForgotPasswordKeyOnlyTest.php new file mode 100644 index 0000000..e68711c --- /dev/null +++ b/tests/Feature/ForgotPasswordKeyOnlyTest.php @@ -0,0 +1,33 @@ +create(['must_change_password' => false]); + WebauthnCredential::create(['user_id' => $user->id, 'name' => 'k', 'credential_id' => 'cid', 'public_key' => '{}', 'sign_count' => 0]); + $codes = $user->fresh()->replaceRecoveryCodes(); + + Livewire::test(ForgotPassword::class) + ->set('email', $user->email) + ->set('code', $codes[0]) + ->set('password', 'brand-New-Pass-9') + ->set('password_confirmation', 'brand-New-Pass-9') + ->call('resetPassword') + ->assertRedirect(route('login')); + + $this->assertTrue(Hash::check('brand-New-Pass-9', $user->fresh()->password)); + } +}