The solution is to use multiple throttle keys as follows:
/**
* @return \Illuminate\Config\Repository|\Illuminate\Contracts\Foundation\Application|mixed
*/
private function getRateLimits()
{
$passwordRateLimit = config('auth.password_rate_limit', [60 => 5]);
krsort($passwordRateLimit);
return $passwordRateLimit;
}
/**
* Increment the rate limiter
*
* @return mixed
*/
protected function failLogin()
{
foreach (array_keys($this->getRateLimits()) as $decaySeconds) {
RateLimiter::hit($this->throttleKey($decaySeconds), $decaySeconds);
}
throw ValidationException::withMessages([
'email' => trans('auth.failed'),
]);
}
// authenticate function
/**
* Ensure the login request is not rate limited.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function ensureIsNotRateLimited(): void
{
foreach ($this->getRateLimits() as $decaySeconds => $maxAttempts) {
if (RateLimiter::tooManyAttempts($this->throttleKey($decaySeconds), $maxAttempts)) {
$seconds = RateLimiter::availableIn($this->throttleKey($decaySeconds));
event(new Lockout($this));
throw ValidationException::withMessages([
'email' => trans('auth.throttle', [
'seconds' => $seconds,
]),
]);
}
}
}
/**
* Get the rate limiting throttle key for the request.
*/
public function throttleKey($interval = ''): string
{
return Str::transliterate(Str::lower($this->input('email')).'|'.$this->ip().'|'.$interval);
}
Then in config/auth.php, configure as required:
/*
|--------------------------------------------------------------------------
| Login Throttling
|--------------------------------------------------------------------------
|
| Here you can define how many logins a user can attempt before
| being throttled. The key is the decay in seconds and the value is
| amount of attempts.
|
*/
'password_rate_limit' => [
120=> 5,
3600 => 15,
86400 => 30,
]