To log the event where the failed login limit is exceeded (triggered by the RateLimiter), we need to handle the TooManyLoginAttemptsAuthenticationException. This exception is thrown by the LoginThrottlingListener.
We will handle this in the onLoginFailureEvent method within a subscriber.

In this case, we cannot immediately retrieve the User from the event.
When the failed login limit is exceeded, the user is null and the User Loader is not set, attempting to retrieve the User results in a LogicException:

No user loader is configured, did you forget to register the "Symfony\Component\Security\Http\EventListener\UserProviderListener" listener?

Therefore, in this case, the user identifier is first retrieved from the UserBadge, and only then is the user fetched from the UserProvider. Alternatively, the user can be retrieved directly from the database.

The else block handles standard failed login attempts.

src/EventSubscriber/ActivityLogSubscriber.php

use App\Entity\User\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Exception\TooManyLoginAttemptsAuthenticationException;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Event\LoginFailureEvent;
use App\Security\UserProvider;

class ActivityLogSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private EntityManagerInterface $em,
        private UserProvider $userProvider,
    ) {
    }

    public function onLoginFailureEvent(LoginFailureEvent $event): void
    {
        $passport = $event->getPassport();

        $exception = $event->getException();
        if ($exception instanceof TooManyLoginAttemptsAuthenticationException) {
            $userIdentifier = $passport->getBadge(UserBadge::class)->getUserIdentifier();
            $user = $this->userProvider->loadUserByIdentifier($userIdentifier);

            // log to entity $activityLog
        } else {
            $user = $passport->getUser();

            // log to entity $activityLog
        }

        $this->em->persist($activityLog);
        $this->em->flush();
    }

    public static function getSubscribedEvents(): array
    {
        return [
            LoginFailureEvent::class => 'onLoginFailureEvent',
        ];
    }
}