custom/plugins/BartCTwoFactorAuth/src/Api/Controller/TfaController.php line 117

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace BartCTwoFactorAuth\Api\Controller;
  3. use BartCTwoFactorAuth\Extension\System\User\UserExtensionEntity;
  4. use PragmaRX\Google2FA\Google2FA;
  5. use Shopware\Core\Framework\Api\Context\AdminApiSource;
  6. use Shopware\Core\Framework\Api\Response\ResponseFactoryInterface;
  7. use Shopware\Core\Framework\Context;
  8. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  11. use Shopware\Core\Framework\Routing\Annotation\Since;
  12. use Shopware\Storefront\Controller\StorefrontController;
  13. use Symfony\Component\HttpFoundation\JsonResponse;
  14. use Symfony\Component\HttpFoundation\Request;
  15. use Symfony\Component\Routing\Annotation\Route;
  16. use Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface;
  17. /**
  18.  * @Route(defaults={"_routeScope"={"api"}})
  19.  */
  20. class TfaController extends StorefrontController
  21. {
  22.     private EntityRepositoryInterface $tfaRepository;
  23.     public function __construct(
  24.         EntityRepositoryInterface $tfaRepository,
  25.         TokenGeneratorInterface $tokenGenerator
  26.     ) {
  27.         $this->tfaRepository $tfaRepository;
  28.     }
  29.     /**
  30.      * @Since("6.0.0.0")
  31.      * @Route("/api/tfa/checkifenabled", name="api.tfa.checkifenabled", methods={"GET"})
  32.      */
  33.     public function checkIfEnabled(Context $contextRequest $requestResponseFactoryInterface $responseFactory): JsonResponse
  34.     {
  35.         $tfaEnabled false;
  36.         $userId $request->get('userId');
  37.         $criteria = new Criteria();
  38.         $criteria->addFilter(new EqualsFilter('userId'$userId));
  39.         $tfa $this->tfaRepository->search($criteria$context)->first();
  40.         if ($tfa !== null) {
  41.             $tfaEnabled $tfa->getTfaStatus();
  42.         }
  43.         return $this->json([
  44.             'tfaEnabled' => $tfaEnabled
  45.         ]);
  46.     }
  47.     /**
  48.      * @Since("6.0.0.0")
  49.      * @Route("/api/tfa/checkcode", name="api.tfa.check", methods={"GET"})
  50.      */
  51.     public function checkCode(Context $contextRequest $requestResponseFactoryInterface $responseFactory): JsonResponse
  52.     {
  53.         $tfaSecret $request->get('tfaSecret');
  54.         $tfaUserCode $request->get('tfaUserCode''');
  55.         $valid false;
  56.         $token '';
  57.         $user $this->getUserWithTfa($request$context);
  58.         if ($user) {
  59.             if (!$tfaSecret) {
  60.                 $tfaSecret $user->getTfaSecret();
  61.             }
  62.             $google2fa = new Google2FA();
  63.             $valid $google2fa->verifyKey(
  64.                 $tfaSecret,
  65.                 $tfaUserCode,
  66.                 8
  67.             );
  68.             if (!$valid && $tfaUserCode !== '' && $user->getBackupCode() !== null) {
  69.                 $valid $tfaUserCode === $user->getBackupCode();
  70.                 if ($valid) {
  71.                     $this->tfaRepository->update([
  72.                         [
  73.                             'id' => $user->getId(),
  74.                             'backupCode' => null
  75.                         ]
  76.                     ], $context);
  77.                 }
  78.             }
  79.             if ($valid) {
  80.                 $token $this->generateToken();
  81.                 $this->tfaRepository->update([
  82.                     [
  83.                         'id' => $user->getId(),
  84.                         'tfaToken' => $token,
  85.                         'tfaTokenCreated' => (new \DateTime())
  86.                     ]
  87.                 ], $context);
  88.             }
  89.         }
  90.         return $this->json([
  91.             'valid' => $valid,
  92.             'token' => $token
  93.         ]);
  94.     }
  95.     /**
  96.      * @Since("6.0.0.0")
  97.      * @Route("/api/tfa/checktfatoken", name="api.tfa.checktfatoken", methods={"GET"})
  98.      */
  99.     public function checkTfaToken(Context $contextRequest $requestResponseFactoryInterface $responseFactory): JsonResponse
  100.     {
  101.         $valid false;
  102.         $tfaToken $request->get('tfaToken');
  103.         $user $this->getUserWithTfa($request$context);
  104.         if ($user) {
  105.             $tfaTokenCreated $user->getTfaTokenCreated();
  106.             if ($tfaTokenCreated->diff(new \DateTime())->days 7) {
  107.                 $valid $tfaToken === $user->getTfaToken();
  108.             } else {
  109.                 $this->tfaRepository->update([
  110.                     [
  111.                         'id' => $user->getId(),
  112.                         'tfaToken' => null,
  113.                         'tfaTokenCreated' => null
  114.                     ]
  115.                 ], $context);
  116.             }
  117.         }
  118.         return $this->json([
  119.             'valid' => $valid
  120.         ]);
  121.     }
  122.     /**
  123.      * @Route("api/tfa/generate", name="frontend.tfa.generate", methods={"GET"})
  124.      */
  125.     public function generate(): JsonResponse
  126.     {
  127.         $google2fa = new Google2FA();
  128.         $secret $google2fa->generateSecretKey();
  129.         $text $google2fa->getQRCodeUrl(
  130.             'Compmany',
  131.             'Holder',
  132.             $secret
  133.         );
  134.         $json file_get_contents('https://scintillating-paprenjak-462850.netlify.app/.netlify/functions/qrGenerator?data=' .
  135.             urlencode(utf8_encode($text)));
  136.         $data json_decode($jsontrue);
  137.         if ($data === null || !isset($data['imageUrl'])) {
  138.             return $this->json([
  139.                 'error' => 'Could not generate QR code'
  140.             ]);
  141.         }
  142.         return $this->json([
  143.             'tfaQrCode' => $data['imageUrl'],
  144.             'tfaSecret' => $secret,
  145.         ]);
  146.     }
  147.     private function generateToken(): string
  148.     {
  149.         $bytes random_bytes(256 8);
  150.         return rtrim(strtr(base64_encode($bytes), '+/''-_'), '=');
  151.     }
  152.     private function getUserWithTfa(Request $requestContext $context): ?UserExtensionEntity
  153.     {
  154.         $userId $request->get('userId');
  155.         $adminApiSource $context->getSource();
  156.         if ($userId === null && $adminApiSource instanceof AdminApiSource) {
  157.             $userId $adminApiSource->getUserId();
  158.         }
  159.         $criteria = new Criteria();
  160.         $criteria->addFilter(new EqualsFilter('userId'$userId));
  161.         return $this->tfaRepository->search($criteria$context)->first();
  162.     }
  163. }