custom/plugins/IwvTwoFactorAuthentication/src/Subscriber/StoreFrontSubscriber.php line 83

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Iwv\IwvTwoFactorAuthentication\Subscriber;
  4. use Exception;
  5. use League\OAuth2\Server\Exception\OAuthServerException;
  6. use Shopware\Core\Checkout\Customer\CustomerEntity;
  7. use Shopware\Core\PlatformRequest;
  8. use Shopware\Core\Framework\Context;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  12. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  15. use Symfony\Component\HttpFoundation\Response;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\HttpKernel\KernelEvents;
  18. use Iwv\IwvTwoFactorAuthentication\Service\TwoFactorAdaptors\GoogleAuthenticatorAdaptor;
  19. use Iwv\IwvTwoFactorAuthentication\Service\TwoFactorAdaptors\YubicoAuthenticatorAdaptor;
  20. use Iwv\IwvTwoFactorAuthentication\Service\StoreFrontCookieHelperValidator;
  21. use Iwv\IwvTwoFactorAuthentication\Service\SessionHelpers\StoreFrontSessionTokenHelper;
  22. class StoreFrontSubscriber implements EventSubscriberInterface
  23. {
  24.     /**
  25.      * @var EntityRepositoryInterface
  26.      */
  27.     private $userRepository;
  28.     /**
  29.      * @var EntityRepositoryInterface
  30.      */
  31.     private $customerRepository;
  32.     /**
  33.      * @var StoreFrontSessionTokenHelper
  34.      */
  35.     private $storeFrontSessionTokenHelper;
  36.         /**
  37.      * @var StoreFrontCookieHelperValidator
  38.      */
  39.     private $storeFrontCookieHelperValidator;
  40.     /**
  41.      * @var GoogleAuthenticatorAdaptor
  42.      */
  43.     private $googleAuthenticatorAdaptor;
  44.     /**
  45.      * @var YubicoAuthenticatorAdaptor
  46.      */
  47.     private $yubicoAuthenticatorAdaptor;
  48.     public function __construct(
  49.         EntityRepositoryInterface $userRepository,
  50.         EntityRepositoryInterface $customerRepository,
  51.         StoreFrontCookieHelperValidator $storeFrontCookieHelperValidator,
  52.         StoreFrontSessionTokenHelper $storeFrontSessionTokenHelper,
  53.         GoogleAuthenticatorAdaptor $googleAuthenticatorAdaptor,
  54.         YubicoAuthenticatorAdaptor $yubicoAuthenticatorAdaptor
  55.     ) {
  56.         $this->userRepository $userRepository;
  57.         $this->customerRepository $customerRepository;
  58.         $this->storeFrontCookieHelperValidator $storeFrontCookieHelperValidator;
  59.         $this->storeFrontSessionTokenHelper $storeFrontSessionTokenHelper;
  60.         $this->googleAuthenticatorAdaptor $googleAuthenticatorAdaptor;
  61.         $this->yubicoAuthenticatorAdaptor $yubicoAuthenticatorAdaptor;
  62.     }
  63.     public static function getSubscribedEvents()
  64.     {
  65.         return [
  66.             KernelEvents::RESPONSE => 'onResponse',
  67.         ];
  68.     }
  69.     public function onResponse(ResponseEvent $event): void
  70.     {
  71.         /** @var \Symfony\Component\HttpFoundation\Request $request */
  72.         $request $event->getRequest();
  73.         /** @var \Symfony\Component\HttpFoundation\JsonResponse $response */
  74.         $response $event->getResponse();
  75.         /* return on invalid requests */
  76.         if (!in_array($event->getResponse()->getStatusCode(), [200204])) {
  77.             return;
  78.         }
  79.         /* $event->getContext() does not exists */
  80.         $context $request->attributes->get(PlatformRequest::ATTRIBUTE_CONTEXT_OBJECT);
  81.         /* update cookie request on profiles change */
  82.         if ($request->attributes->get('_route') === 'frontend.account.iwvtwofactor.yubico' || 
  83.             $request->attributes->get('_route') === 'frontend.account.iwvtwofactor.yubico.disable' || 
  84.             $request->attributes->get('_route') === 'frontend.account.iwvtwofactor.otp' || 
  85.             $request->attributes->get('_route') === 'frontend.account.iwvtwofactor.otp.disable'
  86.         
  87.         {
  88.             /** @var SalesChannelContext $salesChannelContext */
  89.             $salesChannelContext $request->attributes->get('sw-sales-channel-context');
  90.             $customerId $salesChannelContext->getCustomer()->getId();
  91.             if ($customerId) {
  92.                 $customerDB $context->scope(Context::SYSTEM_SCOPE, fn(Context $systemContext) => $this->customerRepository->search(new Criteria([$customerId]), $systemContext)->first());
  93.                 $customFields $customerDB->getCustomFields();
  94.                 $twoFaParams $customFields['iwvTwoFactor'] ?? [];
  95.                 $response = !empty($twoFaParams) ? $this->storeFrontCookieHelperValidator->addTwoFaCookie($response$customerDB) : $this->storeFrontCookieHelperValidator->removeTwoFaCookie($response);
  96.                 $event->setResponse($response);
  97.             }
  98.             return;
  99.         }
  100.         // if(!$request->attributes->get('_loginRequired')){
  101.         //     return;
  102.         // }
  103.         $salesChannelContext $request->attributes->get('sw-sales-channel-context');
  104.         if(!$salesChannelContext){
  105.             return;
  106.         }
  107.         $customerId null;
  108.         if($salesChannelContext->getCustomer()){
  109.             $customerId $salesChannelContext->getCustomer()->getId();
  110.         }
  111.         
  112.         if(!$customerId){
  113.             return;
  114.         }
  115.          /** @var CustomerEntity $customerDB */
  116.         $customerDB $context->scope(Context::SYSTEM_SCOPE, fn(Context $systemContext) => $this->customerRepository->search((new Criteria())->addFilter(new EqualsFilter('id'$customerId)), $systemContext)->first());
  117.         if (!$customerDB || !($customFields $customerDB->getCustomFields()) || !isset($customFields['iwvTwoFactor']) || empty($customFields['iwvTwoFactor'])){
  118.             return;
  119.         }
  120.         try {
  121.             $response $this->storeFrontCookieHelperValidator->addTwoFaCookie($response$customerDB);
  122.             $response $this->storeFrontSessionTokenHelper->addTwoFaSessionCookie($context$response$customerDB);
  123.             $event->setResponse($response);
  124.         } catch (\Exception $ex) {
  125.             throw new OAuthServerException('OTP is required'$ex->getCode(), 'iwv-request-otp'401array_keys($customFields['iwvTwoFactor']) ?? $customFields['iwvTwoFactor']);
  126.         }
  127.     }
  128. }