Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[RateLimiter] Throws strange error about DateTimeImmutable when using sliding_window since Symfony 5.4 #45254

Copy link
Copy link
Closed
@wornet-aer

Description

@wornet-aer
Issue body actions

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.