fix: Login failed event

This commit is contained in:
Dan Harrin
2025-07-28 17:37:04 +01:00
parent 584fb2c2e6
commit 2579b3105e
2 changed files with 62 additions and 5 deletions
+18 -5
View File
@@ -27,14 +27,17 @@ use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Schema;
use Filament\Support\Enums\Alignment;
use Filament\View\PanelsRenderHook;
use Illuminate\Auth\Events\Failed;
use Illuminate\Auth\SessionGuard;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
use Illuminate\Validation\ValidationException;
use Livewire\Attributes\Locked;
use SensitiveParameter;
/**
* @property-read Action $registerAction
@@ -74,7 +77,10 @@ class Login extends SimplePage
$data = $this->form->getState();
$authProvider = Filament::auth()->getProvider(); /** @phpstan-ignore-line */
/** @var SessionGuard $authGuard */
$authGuard = Filament::auth();
$authProvider = $authGuard->getProvider(); /** @phpstan-ignore-line */
$credentials = $this->getCredentialsFromFormData($data);
$user = $authProvider->retrieveByCredentials($credentials);
@@ -82,6 +88,7 @@ class Login extends SimplePage
if ((! $user) || (! $authProvider->validateCredentials($user, $credentials))) {
$this->userUndertakingMultiFactorAuthentication = null;
$this->fireFailedEvent($authGuard, $user, $credentials);
$this->throwFailureValidationException();
}
@@ -112,9 +119,6 @@ class Login extends SimplePage
}
}
/** @var SessionGuard $authGuard */
$authGuard = Filament::auth();
if (! $authGuard->attemptWhen($credentials, function (Authenticatable $user): bool {
if (! ($user instanceof FilamentUser)) {
return true;
@@ -122,6 +126,7 @@ class Login extends SimplePage
return $user->canAccessPanel(Filament::getCurrentOrDefaultPanel());
}, $data['remember'] ?? false)) {
$this->fireFailedEvent($authGuard, $user, $credentials);
$this->throwFailureValidationException();
}
@@ -144,6 +149,14 @@ class Login extends SimplePage
->danger();
}
/**
* @param array<string, mixed> $credentials
*/
protected function fireFailedEvent(Guard $guard, ?Authenticatable $user, #[SensitiveParameter] array $credentials): void
{
event(app(Failed::class, ['guard' => $guard->name, 'user' => $user, 'credentials' => $credentials]));
}
protected function throwFailureValidationException(): never
{
throw ValidationException::withMessages([
@@ -352,7 +365,7 @@ class Login extends SimplePage
* @param array<string, mixed> $data
* @return array<string, mixed>
*/
protected function getCredentialsFromFormData(array $data): array
protected function getCredentialsFromFormData(#[SensitiveParameter] array $data): array
{
return [
'email' => $data['email'],
+44
View File
@@ -4,6 +4,8 @@ use Filament\Auth\Pages\Login;
use Filament\Facades\Filament;
use Filament\Tests\Fixtures\Models\User;
use Filament\Tests\TestCase;
use Illuminate\Auth\Events\Failed;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Str;
use function Filament\Tests\livewire;
@@ -61,6 +63,8 @@ it('can redirect unauthenticated app requests', function (): void {
});
it('cannot authenticate with incorrect credentials', function (): void {
Event::fake([Failed::class]);
$userToAuthenticate = User::factory()->create();
livewire(Login::class)
@@ -72,9 +76,30 @@ it('cannot authenticate with incorrect credentials', function (): void {
->assertHasFormErrors(['email']);
$this->assertGuest();
Event::assertDispatched(function (Failed $event) use ($userToAuthenticate) {
if ($event->guard !== 'web') {
return false;
}
if (! $event->user->is($userToAuthenticate)) {
return false;
}
if ($event->credentials !== [
'email' => $userToAuthenticate->email,
'password' => 'incorrect-password',
]) {
return false;
}
return true;
});
});
it('cannot authenticate on unauthorized panel', function (): void {
Event::fake([Failed::class]);
$userToAuthenticate = User::factory()->create();
Filament::setCurrentPanel('custom');
@@ -88,6 +113,25 @@ it('cannot authenticate on unauthorized panel', function (): void {
->assertHasFormErrors(['email']);
$this->assertGuest();
Event::assertDispatched(function (Failed $event) use ($userToAuthenticate) {
if ($event->guard !== 'web') {
return false;
}
if (! $event->user->is($userToAuthenticate)) {
return false;
}
if ($event->credentials !== [
'email' => $userToAuthenticate->email,
'password' => 'password',
]) {
return false;
}
return true;
});
});
it('can throttle authentication attempts', function (): void {