vendor/symfony/security/Guard/Firewall/GuardAuthenticationListener.php line 33

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <[email protected]>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Security\Guard\Firewall;
  11. use Psr\Log\LoggerInterface;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use Symfony\Component\HttpKernel\Event\GetResponseEvent;
  15. use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
  16. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  17. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  18. use Symfony\Component\Security\Guard\AuthenticatorInterface;
  19. use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
  20. use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
  21. use Symfony\Component\Security\Http\Firewall\ListenerInterface;
  22. use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
  23. /**
  24.  * Authentication listener for the "guard" system.
  25.  *
  26.  * @author Ryan Weaver <[email protected]>
  27.  * @author Amaury Leroux de Lens <[email protected]>
  28.  */
  29. class GuardAuthenticationListener implements ListenerInterface
  30. {
  31.     private $guardHandler;
  32.     private $authenticationManager;
  33.     private $providerKey;
  34.     private $guardAuthenticators;
  35.     private $logger;
  36.     private $rememberMeServices;
  37.     /**
  38.      * @param GuardAuthenticatorHandler         $guardHandler          The Guard handler
  39.      * @param AuthenticationManagerInterface    $authenticationManager An AuthenticationManagerInterface instance
  40.      * @param string                            $providerKey           The provider (i.e. firewall) key
  41.      * @param iterable|AuthenticatorInterface[] $guardAuthenticators   The authenticators, with keys that match what's passed to GuardAuthenticationProvider
  42.      * @param LoggerInterface                   $logger                A LoggerInterface instance
  43.      */
  44.     public function __construct(GuardAuthenticatorHandler $guardHandlerAuthenticationManagerInterface $authenticationManagerstring $providerKey$guardAuthenticatorsLoggerInterface $logger null)
  45.     {
  46.         if (empty($providerKey)) {
  47.             throw new \InvalidArgumentException('$providerKey must not be empty.');
  48.         }
  49.         $this->guardHandler $guardHandler;
  50.         $this->authenticationManager $authenticationManager;
  51.         $this->providerKey $providerKey;
  52.         $this->guardAuthenticators $guardAuthenticators;
  53.         $this->logger $logger;
  54.     }
  55.     /**
  56.      * Iterates over each authenticator to see if each wants to authenticate the request.
  57.      */
  58.     public function handle(GetResponseEvent $event)
  59.     {
  60.         if (null !== $this->logger) {
  61.             $context = array('firewall_key' => $this->providerKey);
  62.             if ($this->guardAuthenticators instanceof \Countable || \is_array($this->guardAuthenticators)) {
  63.                 $context['authenticators'] = \count($this->guardAuthenticators);
  64.             }
  65.             $this->logger->debug('Checking for guard authentication credentials.'$context);
  66.         }
  67.         foreach ($this->guardAuthenticators as $key => $guardAuthenticator) {
  68.             // get a key that's unique to *this* guard authenticator
  69.             // this MUST be the same as GuardAuthenticationProvider
  70.             $uniqueGuardKey $this->providerKey.'_'.$key;
  71.             $this->executeGuardAuthenticator($uniqueGuardKey$guardAuthenticator$event);
  72.             if ($event->hasResponse()) {
  73.                 if (null !== $this->logger) {
  74.                     $this->logger->debug('The "{authenticator}" authenticator set the response. Any later authenticator will not be called', array('authenticator' => \get_class($guardAuthenticator)));
  75.                 }
  76.                 break;
  77.             }
  78.         }
  79.     }
  80.     private function executeGuardAuthenticator($uniqueGuardKeyAuthenticatorInterface $guardAuthenticatorGetResponseEvent $event)
  81.     {
  82.         $request $event->getRequest();
  83.         try {
  84.             if (null !== $this->logger) {
  85.                 $this->logger->debug('Calling getCredentials() on guard configurator.', array('firewall_key' => $this->providerKey'authenticator' => \get_class($guardAuthenticator)));
  86.             }
  87.             // abort the execution of the authenticator if it doesn't support the request
  88.             if (!$guardAuthenticator->supports($request)) {
  89.                 return;
  90.             }
  91.             // allow the authenticator to fetch authentication info from the request
  92.             $credentials $guardAuthenticator->getCredentials($request);
  93.             if (null === $credentials) {
  94.                 throw new \UnexpectedValueException(sprintf('The return value of "%1$s::getCredentials()" must not be null. Return false from "%1$s::supports()" instead.', \get_class($guardAuthenticator)));
  95.             }
  96.             // create a token with the unique key, so that the provider knows which authenticator to use
  97.             $token = new PreAuthenticationGuardToken($credentials$uniqueGuardKey);
  98.             if (null !== $this->logger) {
  99.                 $this->logger->debug('Passing guard token information to the GuardAuthenticationProvider', array('firewall_key' => $this->providerKey'authenticator' => \get_class($guardAuthenticator)));
  100.             }
  101.             // pass the token into the AuthenticationManager system
  102.             // this indirectly calls GuardAuthenticationProvider::authenticate()
  103.             $token $this->authenticationManager->authenticate($token);
  104.             if (null !== $this->logger) {
  105.                 $this->logger->info('Guard authentication successful!', array('token' => $token'authenticator' => \get_class($guardAuthenticator)));
  106.             }
  107.             // sets the token on the token storage, etc
  108.             $this->guardHandler->authenticateWithToken($token$request$this->providerKey);
  109.         } catch (AuthenticationException $e) {
  110.             // oh no! Authentication failed!
  111.             if (null !== $this->logger) {
  112.                 $this->logger->info('Guard authentication failed.', array('exception' => $e'authenticator' => \get_class($guardAuthenticator)));
  113.             }
  114.             $response $this->guardHandler->handleAuthenticationFailure($e$request$guardAuthenticator$this->providerKey);
  115.             if ($response instanceof Response) {
  116.                 $event->setResponse($response);
  117.             }
  118.             return;
  119.         }
  120.         // success!
  121.         $response $this->guardHandler->handleAuthenticationSuccess($token$request$guardAuthenticator$this->providerKey);
  122.         if ($response instanceof Response) {
  123.             if (null !== $this->logger) {
  124.                 $this->logger->debug('Guard authenticator set success response.', array('response' => $response'authenticator' => \get_class($guardAuthenticator)));
  125.             }
  126.             $event->setResponse($response);
  127.         } else {
  128.             if (null !== $this->logger) {
  129.                 $this->logger->debug('Guard authenticator set no success response: request continues.', array('authenticator' => \get_class($guardAuthenticator)));
  130.             }
  131.         }
  132.         // attempt to trigger the remember me functionality
  133.         $this->triggerRememberMe($guardAuthenticator$request$token$response);
  134.     }
  135.     /**
  136.      * Should be called if this listener will support remember me.
  137.      */
  138.     public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices)
  139.     {
  140.         $this->rememberMeServices $rememberMeServices;
  141.     }
  142.     /**
  143.      * Checks to see if remember me is supported in the authenticator and
  144.      * on the firewall. If it is, the RememberMeServicesInterface is notified.
  145.      */
  146.     private function triggerRememberMe(AuthenticatorInterface $guardAuthenticatorRequest $requestTokenInterface $tokenResponse $response null)
  147.     {
  148.         if (null === $this->rememberMeServices) {
  149.             if (null !== $this->logger) {
  150.                 $this->logger->debug('Remember me skipped: it is not configured for the firewall.', array('authenticator' => \get_class($guardAuthenticator)));
  151.             }
  152.             return;
  153.         }
  154.         if (!$guardAuthenticator->supportsRememberMe()) {
  155.             if (null !== $this->logger) {
  156.                 $this->logger->debug('Remember me skipped: your authenticator does not support it.', array('authenticator' => \get_class($guardAuthenticator)));
  157.             }
  158.             return;
  159.         }
  160.         if (!$response instanceof Response) {
  161.             throw new \LogicException(sprintf(
  162.                 '%s::onAuthenticationSuccess *must* return a Response if you want to use the remember me functionality. Return a Response, or set remember_me to false under the guard configuration.',
  163.                 \get_class($guardAuthenticator)
  164.             ));
  165.         }
  166.         $this->rememberMeServices->loginSuccess($request$response$token);
  167.     }
  168. }