From 50132587a186347ec288f85f43e158cb3b4273da Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Sun, 26 Jan 2020 15:37:32 +0100 Subject: [PATCH] Add provider key in PreAuthenticationGuardToken This is required to create the correct authenticated token in the GuardAuthenticationManager. --- .../DependencyInjection/SecurityExtension.php | 37 ++++++++++++------- .../GuardAuthenticationManager.php | 2 +- .../GuardAuthenticatorListenerTrait.php | 2 +- .../Provider/GuardAuthenticationProvider.php | 2 +- .../GuardAuthenticationProviderTrait.php | 4 +- .../Token/PreAuthenticationGuardToken.php | 14 +++++-- .../Http/Firewall/GuardManagerListener.php | 2 +- 7 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 55ebd0d62f..94450d2461 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -269,19 +269,6 @@ class SecurityExtension extends Extension implements PrependExtensionInterface if ($this->guardAuthenticationManagerEnabled) { $authenticationManagerId = 'security.authentication.manager.guard'; $container->setAlias('security.authentication.manager', new Alias($authenticationManagerId)); - - // guard authentication manager listener - $container - ->setDefinition('security.firewall.guard.'.$name.'locator', new ChildDefinition('security.firewall.guard.locator')) - ->setArguments([$authenticationProviders]) - ->addTag('container.service_locator') - ; - $container - ->setDefinition('security.firewall.guard.'.$name, new ChildDefinition('security.firewall.guard')) - ->replaceArgument(2, new Reference('security.firewall.guard.'.$name.'locator')) - ->replaceArgument(3, $name) - ->addTag('kernel.event_listener', ['event' => KernelEvents::REQUEST]) - ; } $container ->getDefinition($authenticationManagerId) @@ -431,7 +418,29 @@ class SecurityExtension extends Extension implements PrependExtensionInterface $configuredEntryPoint = isset($firewall['entry_point']) ? $firewall['entry_point'] : null; // Authentication listeners - list($authListeners, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $authenticationProviders, $defaultProvider, $providerIds, $configuredEntryPoint, $contextListenerId); + $firewallAuthenticationProviders = []; + list($authListeners, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $firewallAuthenticationProviders, $defaultProvider, $providerIds, $configuredEntryPoint, $contextListenerId); + + $authenticationProviders = array_merge($authenticationProviders, $firewallAuthenticationProviders); + + if ($this->guardAuthenticationManagerEnabled) { + // guard authentication manager listener + $container + ->setDefinition('security.firewall.guard.'.$id.'.locator', new ChildDefinition('security.firewall.guard.locator')) + ->setArguments([array_map(function ($id) { + return new Reference($id); + }, $firewallAuthenticationProviders)]) + ->addTag('container.service_locator') + ; + $container + ->setDefinition('security.firewall.guard.'.$id, new ChildDefinition('security.firewall.guard')) + ->replaceArgument(2, new Reference('security.firewall.guard.'.$id.'.locator')) + ->replaceArgument(3, $id) + ->addTag('kernel.event_listener', ['event' => KernelEvents::REQUEST]) + ; + + $listeners[] = new Reference('security.firewall.guard.'.$id); + } $config->replaceArgument(7, $configuredEntryPoint ?: $defaultEntryPoint); diff --git a/src/Symfony/Component/Security/Core/Authentication/GuardAuthenticationManager.php b/src/Symfony/Component/Security/Core/Authentication/GuardAuthenticationManager.php index 0afa2121aa..624b0a678c 100644 --- a/src/Symfony/Component/Security/Core/Authentication/GuardAuthenticationManager.php +++ b/src/Symfony/Component/Security/Core/Authentication/GuardAuthenticationManager.php @@ -81,7 +81,7 @@ class GuardAuthenticationManager implements AuthenticationManagerInterface } try { - $result = $this->authenticateViaGuard($guard, $token); + $result = $this->authenticateViaGuard($guard, $token, $token->getProviderKey()); } catch (AuthenticationException $exception) { $this->handleFailure($exception, $token); } diff --git a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticatorListenerTrait.php b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticatorListenerTrait.php index 935f8fa064..043c51c7a8 100644 --- a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticatorListenerTrait.php +++ b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticatorListenerTrait.php @@ -72,7 +72,7 @@ trait GuardAuthenticatorListenerTrait } // create a token with the unique key, so that the provider knows which authenticator to use - $token = new PreAuthenticationGuardToken($credentials, $uniqueGuardKey); + $token = new PreAuthenticationGuardToken($credentials, $uniqueGuardKey, $this->providerKey); if (null !== $this->logger) { $this->logger->debug('Passing guard token information to the GuardAuthenticationProvider', ['firewall_key' => $this->providerKey, 'authenticator' => \get_class($guardAuthenticator)]); diff --git a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php index ac5c4cc2d4..04085aaa05 100644 --- a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php @@ -93,7 +93,7 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface throw new AuthenticationException(sprintf('Token with provider key "%s" did not originate from any of the guard authenticators of provider "%s".', $token->getGuardProviderKey(), $this->providerKey)); } - return $this->authenticateViaGuard($guardAuthenticator, $token); + return $this->authenticateViaGuard($guardAuthenticator, $token, $this->providerKey); } public function supports(TokenInterface $token) diff --git a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProviderTrait.php b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProviderTrait.php index 33e82eb022..0112256b85 100644 --- a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProviderTrait.php +++ b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProviderTrait.php @@ -28,7 +28,7 @@ use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken; */ trait GuardAuthenticationProviderTrait { - private function authenticateViaGuard(AuthenticatorInterface $guardAuthenticator, PreAuthenticationGuardToken $token): GuardTokenInterface + private function authenticateViaGuard(AuthenticatorInterface $guardAuthenticator, PreAuthenticationGuardToken $token, string $providerKey): TokenInterface { // get the user from the GuardAuthenticator $user = $guardAuthenticator->getUser($token->getCredentials(), $this->userProvider); @@ -55,7 +55,7 @@ trait GuardAuthenticationProviderTrait $this->userChecker->checkPostAuth($user); // turn the UserInterface into a TokenInterface - $authenticatedToken = $guardAuthenticator->createAuthenticatedToken($user, $this->providerKey); + $authenticatedToken = $guardAuthenticator->createAuthenticatedToken($user, $providerKey); if (!$authenticatedToken instanceof TokenInterface) { throw new \UnexpectedValueException(sprintf('The "%s::createAuthenticatedToken()" method must return a TokenInterface. You returned "%s".', get_debug_type($guardAuthenticator), get_debug_type($authenticatedToken))); } diff --git a/src/Symfony/Component/Security/Guard/Token/PreAuthenticationGuardToken.php b/src/Symfony/Component/Security/Guard/Token/PreAuthenticationGuardToken.php index 451d96c6ee..460dcf9bda 100644 --- a/src/Symfony/Component/Security/Guard/Token/PreAuthenticationGuardToken.php +++ b/src/Symfony/Component/Security/Guard/Token/PreAuthenticationGuardToken.php @@ -26,15 +26,18 @@ class PreAuthenticationGuardToken extends AbstractToken implements GuardTokenInt { private $credentials; private $guardProviderKey; + private $providerKey; /** - * @param mixed $credentials - * @param string $guardProviderKey Unique key that bind this token to a specific AuthenticatorInterface + * @param mixed $credentials + * @param string $guardProviderKey Unique key that bind this token to a specific AuthenticatorInterface + * @param string|null $providerKey The general provider key (when using with HTTP, this is the firewall name) */ - public function __construct($credentials, string $guardProviderKey) + public function __construct($credentials, string $guardProviderKey, ?string $providerKey = null) { $this->credentials = $credentials; $this->guardProviderKey = $guardProviderKey; + $this->providerKey = $providerKey; parent::__construct([]); @@ -42,6 +45,11 @@ class PreAuthenticationGuardToken extends AbstractToken implements GuardTokenInt parent::setAuthenticated(false); } + public function getProviderKey(): ?string + { + return $this->providerKey; + } + public function getGuardProviderKey() { return $this->guardProviderKey; diff --git a/src/Symfony/Component/Security/Http/Firewall/GuardManagerListener.php b/src/Symfony/Component/Security/Http/Firewall/GuardManagerListener.php index 2cfa86d420..b1261bf2b1 100644 --- a/src/Symfony/Component/Security/Http/Firewall/GuardManagerListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/GuardManagerListener.php @@ -57,7 +57,7 @@ class GuardManagerListener protected function getGuardKey(string $key): string { - // Guard authenticators in the GuardAuthenticationManager are already indexed + // Guard authenticators in the GuardManagerListener are already indexed // by an unique key return $key; }