From 0fd67ee6021bdddb49efb6d4ae2d6f43fd03cf12 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Mon, 2 Mar 2026 14:49:53 +0100 Subject: [PATCH] fix: Login with username (instead of email) (#19387) --- packages/panels/src/Auth/Pages/Login.php | 24 ----------- tests/src/Panels/Auth/LoginTest.php | 55 ------------------------ 2 files changed, 79 deletions(-) diff --git a/packages/panels/src/Auth/Pages/Login.php b/packages/panels/src/Auth/Pages/Login.php index 763de37d3c..76c325a983 100644 --- a/packages/panels/src/Auth/Pages/Login.php +++ b/packages/panels/src/Auth/Pages/Login.php @@ -78,10 +78,6 @@ class Login extends SimplePage $data = $this->form->getState(); - if ($this->isLoginRateLimited($data['email'])) { - return null; - } - /** @var SessionGuard $authGuard */ $authGuard = Filament::auth(); @@ -164,26 +160,6 @@ class Login extends SimplePage return false; } - protected function isLoginRateLimited(string $email): bool - { - $rateLimitingKey = 'filament-login:' . sha1(request()->ip() . '|' . $email); - - if (RateLimiter::tooManyAttempts($rateLimitingKey, maxAttempts: 5)) { - $this->getRateLimitedNotification(new TooManyRequestsException( - static::class, - 'authenticate', - request()->ip(), - RateLimiter::availableIn($rateLimitingKey), - ))?->send(); - - return true; - } - - RateLimiter::hit($rateLimitingKey); - - return false; - } - protected function getRateLimitedNotification(TooManyRequestsException $exception): ?Notification { return Notification::make() diff --git a/tests/src/Panels/Auth/LoginTest.php b/tests/src/Panels/Auth/LoginTest.php index 74e9727dc3..31b48bff95 100644 --- a/tests/src/Panels/Auth/LoginTest.php +++ b/tests/src/Panels/Auth/LoginTest.php @@ -215,61 +215,6 @@ it('can fill the login form, authenticate, and redirect to the dashboard in the ->assertNoAccessibilityIssues(); }); -it('can throttle login attempts per IP and email', function (): void { - $this->assertGuest(); - - $userToAuthenticate = User::factory()->create(); - - // Clear the IP-only rate limiter between attempts to isolate the - // IP+email rate limit. - $clearIpRateLimiter = function (): void { - RateLimiter::clear('livewire-rate-limiter:' . sha1(Login::class . '|authenticate|' . request()->ip())); - }; - - foreach (range(1, 5) as $i) { - $clearIpRateLimiter(); - - livewire(Login::class) - ->fillForm([ - 'email' => $userToAuthenticate->email, - 'password' => 'password', - ]) - ->call('authenticate'); - - $this->assertAuthenticated(); - - auth()->logout(); - } - - $clearIpRateLimiter(); - - // The 6th attempt from the same IP + email should be rate limited - livewire(Login::class) - ->fillForm([ - 'email' => $userToAuthenticate->email, - 'password' => 'password', - ]) - ->call('authenticate') - ->assertNotified(); - - $this->assertGuest(); - - $clearIpRateLimiter(); - - // A different email from the same IP should not be affected - $secondUser = User::factory()->create(); - - livewire(Login::class) - ->fillForm([ - 'email' => $secondUser->email, - 'password' => 'password', - ]) - ->call('authenticate') - ->assertRedirect(Filament::getUrl()); - - $this->assertAuthenticatedAs($secondUser); -}); - it('does not lock out a user when an attacker exhausts login attempts from a different IP', function (): void { $this->assertGuest();