diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 3d030f6ddfd35..9c80198c2a085 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * Add `$badges` argument to `Security::login` * Deprecate the `require_previous_session` config option. Setting it has no effect anymore * Add `LogoutRouteLoader` + * Add `ProgrammaticLoginEvent` event to handle user checks on programmatic login. 6.3 --- diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php index d17254892215c..eaa632f6c19b4 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.php @@ -88,7 +88,7 @@ 'security.authenticator.managers_locator' => service('security.authenticator.managers_locator')->ignoreOnInvalid(), 'request_stack' => service('request_stack'), 'security.firewall.map' => service('security.firewall.map'), - 'security.user_checker' => service('security.user_checker'), + 'event_dispatcher' => service('event_dispatcher'), 'security.firewall.event_dispatcher_locator' => service('security.firewall.event_dispatcher_locator'), 'security.csrf.token_manager' => service('security.csrf.token_manager')->ignoreOnInvalid(), ]), diff --git a/src/Symfony/Bundle/SecurityBundle/Security.php b/src/Symfony/Bundle/SecurityBundle/Security.php index 0c6260356e615..55cd34671fb8f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security.php +++ b/src/Symfony/Bundle/SecurityBundle/Security.php @@ -18,6 +18,7 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; +use Symfony\Component\Security\Core\Event\ProgrammaticLoginEvent; use Symfony\Component\Security\Core\Exception\LogicException; use Symfony\Component\Security\Core\Exception\LogoutException; use Symfony\Component\Security\Core\Security as LegacySecurity; @@ -127,7 +128,7 @@ public function login(UserInterface $user, ?string $authenticatorName = null, ?s $authenticator = $this->getAuthenticator($authenticatorName, $firewallName); - $this->container->get('security.user_checker')->checkPreAuth($user); + $this->container->get('event_dispatcher')->dispatch(new ProgrammaticLoginEvent($user)); return $this->container->get('security.authenticator.managers_locator')->get($firewallName)->authenticateUser($user, $authenticator, $request, $badges); } diff --git a/src/Symfony/Component/Security/Core/Event/ProgrammaticLoginEvent.php b/src/Symfony/Component/Security/Core/Event/ProgrammaticLoginEvent.php new file mode 100644 index 0000000000000..8457ffbde3cea --- /dev/null +++ b/src/Symfony/Component/Security/Core/Event/ProgrammaticLoginEvent.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Event; + +use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Contracts\EventDispatcher\Event; + +/** + * This event is dispatch when login programmatically. + * + * @internal + * + * @author Antoine Makdessi + */ +class ProgrammaticLoginEvent extends Event +{ + private UserInterface $user; + + public function __construct(UserInterface $user) + { + $this->user = $user; + } + + public function getUser(): UserInterface + { + return $this->user; + } +} diff --git a/src/Symfony/Component/Security/Http/EventListener/UserCheckerListener.php b/src/Symfony/Component/Security/Http/EventListener/UserCheckerListener.php index 6a1d4c549cd85..c3a09ebdb6f02 100644 --- a/src/Symfony/Component/Security/Http/EventListener/UserCheckerListener.php +++ b/src/Symfony/Component/Security/Http/EventListener/UserCheckerListener.php @@ -13,6 +13,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent; +use Symfony\Component\Security\Core\Event\ProgrammaticLoginEvent; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PreAuthenticatedUserBadge; @@ -52,11 +53,17 @@ public function postCheckCredentials(AuthenticationSuccessEvent $event): void $this->userChecker->checkPostAuth($user); } + public function onProgrammaticLoginEvent(ProgrammaticLoginEvent $event): void + { + $this->userChecker->checkPreAuth($event->getUser()); + } + public static function getSubscribedEvents(): array { return [ CheckPassportEvent::class => ['preCheckCredentials', 256], AuthenticationSuccessEvent::class => ['postCheckCredentials', 256], + ProgrammaticLoginEvent::class => ['onProgrammaticLoginEvent', 256], ]; } }