diff --git a/src/Events/TwoFactorAuthenticationFailed.php b/src/Events/TwoFactorAuthenticationFailed.php new file mode 100644 index 00000000..105a7679 --- /dev/null +++ b/src/Events/TwoFactorAuthenticationFailed.php @@ -0,0 +1,8 @@ +hasValidCode()) { + event(new TwoFactorAuthenticationFailed($user)); + return app(FailedTwoFactorLoginResponse::class)->toResponse($request); } diff --git a/tests/AuthenticatedSessionControllerWithTwoFactorTest.php b/tests/AuthenticatedSessionControllerWithTwoFactorTest.php index dbc93018..564ef307 100644 --- a/tests/AuthenticatedSessionControllerWithTwoFactorTest.php +++ b/tests/AuthenticatedSessionControllerWithTwoFactorTest.php @@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Hash; use Laravel\Fortify\Events\TwoFactorAuthenticationChallenged; +use Laravel\Fortify\Events\TwoFactorAuthenticationFailed; use Laravel\Fortify\Features; use Laravel\Fortify\Tests\Models\UserWithTwoFactor; use Orchestra\Testbench\Attributes\DefineEnvironment; @@ -200,6 +201,8 @@ public function test_two_factor_authentication_preserves_remember_me_selection() public function test_two_factor_challenge_fails_for_old_otp_and_zero_window() { + Event::fake(); + // Setting window to 0 should mean any old OTP is instantly invalid Features::twoFactorAuthentication(['window' => 0]); @@ -222,6 +225,8 @@ public function test_two_factor_challenge_fails_for_old_otp_and_zero_window() 'code' => $previousOtp, ]); + Event::assertDispatched(TwoFactorAuthenticationFailed::class); + $response->assertRedirect('/two-factor-challenge') ->assertSessionHas('login.id') ->assertSessionHasErrors(['code']);