vendor/scheb/2fa-bundle/Security/Http/EventListener/AbstractCheckCodeListener.php line 29

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Scheb\TwoFactorBundle\Security\Http\EventListener;
  4. use Scheb\TwoFactorBundle\Security\Http\Authenticator\Passport\Credentials\TwoFactorCodeCredentials;
  5. use Scheb\TwoFactorBundle\Security\Http\Authenticator\Passport\TwoFactorPassport;
  6. use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\PreparationRecorderInterface;
  7. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  8. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  9. use Symfony\Component\Security\Http\Event\CheckPassportEvent;
  10. /**
  11. * @internal
  12. */
  13. abstract class AbstractCheckCodeListener implements EventSubscriberInterface
  14. {
  15. /**
  16. * @var PreparationRecorderInterface
  17. */
  18. private $preparationRecorder;
  19. public function __construct(PreparationRecorderInterface $preparationRecorder)
  20. {
  21. $this->preparationRecorder = $preparationRecorder;
  22. }
  23. public function checkPassport(CheckPassportEvent $event): void
  24. {
  25. $passport = $event->getPassport();
  26. if (!($passport instanceof TwoFactorPassport && $passport->hasBadge(TwoFactorCodeCredentials::class))) {
  27. return;
  28. }
  29. /** @var TwoFactorCodeCredentials $credentialsBadge */
  30. $credentialsBadge = $passport->getBadge(TwoFactorCodeCredentials::class);
  31. if ($credentialsBadge->isResolved()) {
  32. return;
  33. }
  34. $token = $passport->getTwoFactorToken();
  35. $providerName = $token->getCurrentTwoFactorProvider();
  36. if (!$providerName) {
  37. throw new AuthenticationException('There is no active two-factor provider.');
  38. }
  39. if (!$this->preparationRecorder->isTwoFactorProviderPrepared($token->getProviderKey(true), $providerName)) {
  40. throw new AuthenticationException(sprintf('The two-factor provider "%s" has not been prepared.', $providerName));
  41. }
  42. $user = $token->getUser();
  43. if (null === $user) {
  44. throw new \RuntimeException('Security token must provide a user.');
  45. }
  46. if ($this->isValidCode($providerName, $user, $credentialsBadge->getCode())) {
  47. $token->setTwoFactorProviderComplete($providerName);
  48. $credentialsBadge->markResolved();
  49. }
  50. }
  51. /**
  52. * @param object|string $user
  53. */
  54. abstract protected function isValidCode(string $providerName, $user, string $code): bool;
  55. }