Closed
Description
Symfony version(s) affected
5.4.*
Description
We've currently updated our environment from Symfony 5.3 to 5.4 and are expieriencing strange RateLimiter errors when using sliding_window
setting. When using Symfony 5.3 there were zero problems with using sliding_window
.
We are using Symfony for an API backend and the error occurs after 1-2h of runtime. Which is really strange... :(
The logfile states the following error:
Exception occurred: Return value of Symfony\Component\RateLimiter\Policy\SlidingWindow::getRetryAfter() must be an instance of DateTimeImmutable, bool returned (Class: TypeError) Trace: #0 /var/www/vhosts/backend/sources/vendor/symfony/rate-limiter/Policy/SlidingWindowLimiter.php(77): Symfony\Component\RateLimiter\Policy\SlidingWindow->getRetryAfter()
How to reproduce
rate_limiter.yaml:
framework:
rate_limiter:
authentication_failed_api:
policy: 'fixed_window'
limit: 5
interval: '60 minutes'
RateLimiter in CustomAuthenticator:
class BasicAuthAuthenticator extends AbstractAuthenticator
{
/**
* @var UserPasswordHasherInterface
*/
protected $passwordHasher;
/**
* @var ParameterBagInterface
*/
private $params;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var EntityManagerInterface
*/
protected $em;
/**
* @var RateLimiterFactory
*/
protected $rateLimiter;
public function __construct(
UserPasswordHasherInterface $passwordHasher,
ParameterBagInterface $params,
LoggerInterface $logger,
EntityManagerInterface $entityManagerInterface,
RateLimiterFactory $authenticationFailedApiLimiter
) {
$this->passwordHasher = $passwordHasher;
$this->params = $params;
$this->logger = $logger;
$this->em = $entityManagerInterface;
$this->rateLimiter = $authenticationFailedApiLimiter;
}
/**
*@see AuthenticatorInterface#authenticate(Request)
* @throws AuthenticationException
* @throws TooManyRequestsException If Client-IP hit rate-limit
* @return Passport
*/
public function authenticate(Request $request): Passport
{
$clientIp = $request->getClientIp();
$limiter = $this->rateLimiter->create($clientIp);
$ipWhitelist = explode(',', $this->params->get(ConfigurationKeys::AUTH_BRUTEFORCE_WHITELIST_NETS));
if (!IpUtils::checkIp($clientIp, $ipWhitelist) && false === $limiter->consume(1)->isAccepted()) {
$this->logger->warning("Authentication failed: Brute-Force limit for IP " . $clientIp . " reached. IP-Address has been temporary blocked/banned now.");
throw new TooManyRequestsException("Too many failed login attempts. Please try again later!");
}
# [...]
return new Passport(new UserBadge($username), new PasswordCredentials($password));
}
/**
* @see AuthenticatorInterface#onAuthenticationSuccess(Request,TokenInterface,string)
* @param string $providerKey The provider (i.e. firewall) key
* @return Response|null Immer null, weil dann der Request einfach weitergeführt wird.
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey): ?Response
{
/** @var PortalUserInterface $user */
$user = $token->getUser();
$realUser = $user->getUser();
$clientIp = $request->getClientIp();
$limiter = $this->rateLimiter->create($clientIp);
$limiter->reset();
# [...]
return null;
}
}
Possible Solution
When using fixed_window
instead, the error doesn't occur and everything works smooth.
Additional Context
No response