diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php index 979acc79dc..5f530a17e2 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php @@ -218,9 +218,8 @@ class RememberMeFactory implements SecurityFactoryInterface, AuthenticatorFactor { $container ->setDefinition('security.listener.remember_me.'.$id, new ChildDefinition('security.listener.remember_me')) - ->addTag('kernel.event_subscriber') + ->addTag('kernel.event_subscriber', ['dispatcher' => 'security.event_dispatcher.'.$id]) ->replaceArgument(0, new Reference($rememberMeServicesId)) - ->replaceArgument(1, $id) ; $container diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index e4ef468c88..35bcf01557 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -156,8 +156,11 @@ class SecurityExtension extends Extension implements PrependExtensionInterface ->replaceArgument(2, $this->statelessFirewallKeys); if ($this->authenticatorManagerEnabled) { - $container->getDefinition(SessionListener::class) - ->replaceArgument(1, $this->statelessFirewallKeys); + foreach ($this->statelessFirewallKeys as $statelessFirewallId) { + $container + ->setDefinition('security.listener.session.'.$statelessFirewallId, new ChildDefinition('security.listener.session')) + ->addTag('kernel.event_subscriber', ['dispatcher' => 'security.event_dispatcher.'.$statelessFirewallId]); + } } if ($config['encoders']) { @@ -446,6 +449,7 @@ class SecurityExtension extends Extension implements PrependExtensionInterface $container ->setDefinition($managerId = 'security.authenticator.manager.'.$id, new ChildDefinition('security.authenticator.manager')) ->replaceArgument(0, $authenticators) + ->replaceArgument(2, new Reference($firewallEventDispatcherId)) ->replaceArgument(3, $id) ->addTag('monolog.logger', ['channel' => 'security']) ; diff --git a/src/Symfony/Bundle/SecurityBundle/EventListener/FirewallEventBubblingListener.php b/src/Symfony/Bundle/SecurityBundle/EventListener/FirewallEventBubblingListener.php index c3415ccc8c..38f819c44f 100644 --- a/src/Symfony/Bundle/SecurityBundle/EventListener/FirewallEventBubblingListener.php +++ b/src/Symfony/Bundle/SecurityBundle/EventListener/FirewallEventBubblingListener.php @@ -12,7 +12,10 @@ namespace Symfony\Bundle\SecurityBundle\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\Security\Http\Event\LoginFailureEvent; +use Symfony\Component\Security\Http\Event\LoginSuccessEvent; use Symfony\Component\Security\Http\Event\LogoutEvent; +use Symfony\Component\Security\Http\Event\VerifyAuthenticatorCredentialsEvent; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** @@ -34,6 +37,9 @@ class FirewallEventBubblingListener implements EventSubscriberInterface { return [ LogoutEvent::class => 'bubbleEvent', + LoginFailureEvent::class => 'bubbleEvent', + LoginSuccessEvent::class => 'bubbleEvent', + VerifyAuthenticatorCredentialsEvent::class => 'bubbleEvent', ]; } diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_authenticator.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_authenticator.xml index 0ff79a0ebd..fc21f87e6c 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_authenticator.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_authenticator.xml @@ -59,8 +59,9 @@ - - + stateless firewall keys diff --git a/src/Symfony/Component/Security/Http/EventListener/RememberMeListener.php b/src/Symfony/Component/Security/Http/EventListener/RememberMeListener.php index 72ce7c13f9..269d232786 100644 --- a/src/Symfony/Component/Security/Http/EventListener/RememberMeListener.php +++ b/src/Symfony/Component/Security/Http/EventListener/RememberMeListener.php @@ -26,26 +26,29 @@ use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; class RememberMeListener implements EventSubscriberInterface { private $rememberMeServices; - private $providerKey; private $logger; - public function __construct(RememberMeServicesInterface $rememberMeServices, string $providerKey, ?LoggerInterface $logger = null) + public function __construct(RememberMeServicesInterface $rememberMeServices, ?LoggerInterface $logger = null) { $this->rememberMeServices = $rememberMeServices; - $this->providerKey = $providerKey; $this->logger = $logger; } public function onSuccessfulLogin(LoginSuccessEvent $event): void { - if (!$this->isRememberMeEnabled($event->getProviderKey(), $event->getAuthenticator())) { + $authenticator = $event->getAuthenticator(); + if (!$authenticator instanceof RememberMeAuthenticatorInterface || !$authenticator->supportsRememberMe()) { + if (null !== $this->logger) { + $this->logger->debug('Remember me skipped: your authenticator does not support it.', ['authenticator' => \get_class($authenticator)]); + } + return; } if (null === $event->getResponse()) { if (null !== $this->logger) { - $this->logger->debug('Remember me skipped: the authenticator did not set a success response.', ['authenticator' => \get_class($event->getAuthenticator())]); + $this->logger->debug('Remember me skipped: the authenticator did not set a success response.', ['authenticator' => \get_class($authenticator)]); } return; @@ -56,31 +59,9 @@ class RememberMeListener implements EventSubscriberInterface public function onFailedLogin(LoginFailureEvent $event): void { - if (!$this->isRememberMeEnabled($event->getProviderKey())) { - return; - } - $this->rememberMeServices->loginFail($event->getRequest(), $event->getException()); } - private function isRememberMeEnabled(string $providerKey, ?AuthenticatorInterface $authenticator = null): bool - { - if ($providerKey !== $this->providerKey) { - // This listener is created for a different firewall. - return false; - } - - if (null !== $authenticator && (!$authenticator instanceof RememberMeAuthenticatorInterface || !$authenticator->supportsRememberMe())) { - if (null !== $this->logger) { - $this->logger->debug('Remember me skipped: your authenticator does not support it.', ['authenticator' => \get_class($authenticator)]); - } - - return false; - } - - return true; - } - public static function getSubscribedEvents(): array { return [ diff --git a/src/Symfony/Component/Security/Http/EventListener/SessionStrategyListener.php b/src/Symfony/Component/Security/Http/EventListener/SessionStrategyListener.php index 436d525a5a..492316ec63 100644 --- a/src/Symfony/Component/Security/Http/EventListener/SessionStrategyListener.php +++ b/src/Symfony/Component/Security/Http/EventListener/SessionStrategyListener.php @@ -28,21 +28,18 @@ use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterfa class SessionStrategyListener implements EventSubscriberInterface { private $sessionAuthenticationStrategy; - private $statelessProviderKeys; - public function __construct(SessionAuthenticationStrategyInterface $sessionAuthenticationStrategy, array $statelessProviderKeys = []) + public function __construct(SessionAuthenticationStrategyInterface $sessionAuthenticationStrategy) { $this->sessionAuthenticationStrategy = $sessionAuthenticationStrategy; - $this->statelessProviderKeys = $statelessProviderKeys; } public function onSuccessfulLogin(LoginSuccessEvent $event): void { $request = $event->getRequest(); $token = $event->getAuthenticatedToken(); - $providerKey = $event->getProviderKey(); - if (!$request->hasSession() || !$request->hasPreviousSession() || \in_array($providerKey, $this->statelessProviderKeys, true)) { + if (!$request->hasSession() || !$request->hasPreviousSession()) { return; }