vendor/scheb/two-factor-bundle/Security/Authentication/Provider/AuthenticationProviderDecorator.php line 70

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Scheb\TwoFactorBundle\Security\Authentication\Provider;
  4. use Scheb\TwoFactorBundle\DependencyInjection\Factory\Security\TwoFactorFactory;
  5. use Scheb\TwoFactorBundle\Security\Authentication\Token\TwoFactorTokenInterface;
  6. use Scheb\TwoFactorBundle\Security\TwoFactor\AuthenticationContextFactoryInterface;
  7. use Scheb\TwoFactorBundle\Security\TwoFactor\Handler\AuthenticationHandlerInterface;
  8. use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
  9. use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
  10. use Symfony\Component\HttpFoundation\Request;
  11. use Symfony\Component\HttpFoundation\RequestStack;
  12. use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
  13. use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
  14. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  15. class AuthenticationProviderDecorator implements AuthenticationProviderInterface
  16. {
  17.     /**
  18.      * @var AuthenticationProviderInterface
  19.      */
  20.     private $decoratedAuthenticationProvider;
  21.     /**
  22.      * @var AuthenticationHandlerInterface
  23.      */
  24.     private $twoFactorAuthenticationHandler;
  25.     /**
  26.      * @var AuthenticationContextFactoryInterface
  27.      */
  28.     private $authenticationContextFactory;
  29.     /**
  30.      * @var FirewallMap
  31.      */
  32.     private $firewallMap;
  33.     /**
  34.      * @var RequestStack
  35.      */
  36.     private $requestStack;
  37.     public function __construct(
  38.         AuthenticationProviderInterface $decoratedAuthenticationProvider,
  39.         AuthenticationHandlerInterface $twoFactorAuthenticationHandler,
  40.         AuthenticationContextFactoryInterface $authenticationContextFactory,
  41.         FirewallMap $firewallMap,
  42.         RequestStack $requestStack
  43.     ) {
  44.         $this->decoratedAuthenticationProvider $decoratedAuthenticationProvider;
  45.         $this->twoFactorAuthenticationHandler $twoFactorAuthenticationHandler;
  46.         $this->authenticationContextFactory $authenticationContextFactory;
  47.         $this->firewallMap $firewallMap;
  48.         $this->requestStack $requestStack;
  49.     }
  50.     public function supports(TokenInterface $token)
  51.     {
  52.         return $this->decoratedAuthenticationProvider->supports($token);
  53.     }
  54.     /**
  55.      * @psalm-suppress InvalidNullableReturnType
  56.      */
  57.     public function authenticate(TokenInterface $token)
  58.     {
  59.         $wasAlreadyAuthenticated $token->isAuthenticated();
  60.         $token $this->decoratedAuthenticationProvider->authenticate($token);
  61.         // Only trigger two-factor authentication when the provider was called with an unauthenticated token. When we
  62.         // get an authenticated token passed, we're not doing a login, but the system refreshes the token. Then we don't
  63.         // want to start two-factor authentication or we're ending in an endless loop.
  64.         if ($wasAlreadyAuthenticated) {
  65.             return $token;
  66.         }
  67.         // AnonymousToken and TwoFactorTokenInterface can be ignored
  68.         // in case of Guard, it can return null due to having multiple guard authenticators (#127, to be removed in v5)
  69.         /** @psalm-suppress DocblockTypeContradiction */
  70.         if ($token instanceof AnonymousToken || $token instanceof TwoFactorTokenInterface || null === $token) {
  71.             /** @psalm-suppress NullableReturnStatement */ return $token;
  72.         }
  73.         $request $this->getRequest();
  74.         $firewallConfig $this->getFirewallConfig($request);
  75.         if (!\in_array(TwoFactorFactory::AUTHENTICATION_PROVIDER_KEY$firewallConfig->getListeners(), true)) {
  76.             return $token// This firewall doesn't support two-factor authentication
  77.         }
  78.         $context $this->authenticationContextFactory->create($request$token$firewallConfig->getName());
  79.         return $this->twoFactorAuthenticationHandler->beginTwoFactorAuthentication($context);
  80.     }
  81.     /**
  82.      * @return mixed
  83.      */
  84.     public function __call(string $method, array $arguments)
  85.     {
  86.         return ($this->decoratedAuthenticationProvider)->{$method}(...$arguments);
  87.     }
  88.     private function getRequest(): Request
  89.     {
  90.         $request $this->requestStack->getMasterRequest();
  91.         if (null === $request) {
  92.             throw new \RuntimeException('No request available');
  93.         }
  94.         return $request;
  95.     }
  96.     private function getFirewallConfig(Request $request): FirewallConfig
  97.     {
  98.         $firewallConfig $this->firewallMap->getFirewallConfig($request);
  99.         if (null === $firewallConfig) {
  100.             throw new \RuntimeException('No firewall configuration available');
  101.         }
  102.         return $firewallConfig;
  103.     }
  104. }