src/Security/LoginFormAuthenticator.php line 207

Open in your IDE?
  1. <?php
  2. namespace App\Security;
  3. use App\Object\Admin\User;
  4. use App\Services\Admin\CustomerService;
  5. use App\Services\Admin\UserService;
  6. use App\Services\Main\ApiService;
  7. use App\Services\Main\SecurityService;
  8. use App\Services\Util\ClockService;
  9. use App\Services\Util\JsonService;
  10. use Symfony\Component\HttpFoundation\RedirectResponse;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpFoundation\RequestStack;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  15. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  16. use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
  17. use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
  18. use Symfony\Component\Security\Core\Security;
  19. use Symfony\Component\Security\Core\User\UserInterface;
  20. use Symfony\Component\Security\Core\User\UserProviderInterface;
  21. use Symfony\Component\Security\Csrf\CsrfToken;
  22. use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
  23. use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
  24. use Symfony\Component\Security\Http\Util\TargetPathTrait;
  25. use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
  26. use Symfony\Contracts\Translation\TranslatorInterface;
  27. /**
  28.  * Class LoginFormAuthenticator.
  29.  */
  30. class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
  31. {
  32.     use TargetPathTrait;
  33.     private const ERROR_DISABLED 'disabledUser';
  34.     private const ERROR_DELETED 'deletedUser';
  35.     private const ERROR_EXPIRED 'expiredCustomer';
  36.     private const ERROR_TWO_AUTH_REQUIRED 'twoAuthRequired';
  37.     /**
  38.      * @var UrlGeneratorInterface
  39.      */
  40.     private UrlGeneratorInterface $urlGenerator;
  41.     /**
  42.      * @var CsrfTokenManagerInterface
  43.      */
  44.     private CsrfTokenManagerInterface $csrfTokenManager;
  45.     /**
  46.      * @var SecurityService
  47.      */
  48.     private SecurityService $securityService;
  49.     /**
  50.      * @var CustomerService
  51.      */
  52.     private CustomerService $customerService;
  53.     private UserService $userService;
  54.     /**
  55.      * @var ApiService
  56.      */
  57.     private ApiService $apiService;
  58.     /**
  59.      * @var Request
  60.      */
  61.     private Request $request;
  62.     /**
  63.      * @var TranslatorInterface
  64.      */
  65.     private TranslatorInterface $translator;
  66.     /**
  67.      * @var ClockService
  68.      */
  69.     private ClockService $clockService;
  70.     /**
  71.      * @var JsonService
  72.      */
  73.     private JsonService $jsonService;
  74.     /**
  75.      * @var RequestStack
  76.      */
  77.     private RequestStack $requestStack;
  78.     /**
  79.      * LoginFormAuthenticator constructor.
  80.      *
  81.      * @param UrlGeneratorInterface $urlGenerator
  82.      * @param SessionInterface $session
  83.      * @param CsrfTokenManagerInterface $csrfTokenManager
  84.      * @param SecurityService $securityService
  85.      * @param CustomerService $customerService
  86.      * @param UserService $userService
  87.      * @param ApiService $apiService
  88.      * @param RequestStack $request
  89.      * @param ClockService $clockService
  90.      * @param JsonService $jsonService
  91.      * @param RequestStack $requestStack
  92.      */
  93.     public function __construct(
  94.         UrlGeneratorInterface $urlGenerator,
  95.         CsrfTokenManagerInterface $csrfTokenManager,
  96.         SecurityService $securityService,
  97.         CustomerService $customerService,
  98.         UserService $userService,
  99.         ApiService $apiService,
  100.         RequestStack $request,
  101.         TranslatorInterface $translator,
  102.         ClockService $clockService,
  103.         JsonService $jsonService,
  104.         RequestStack $requestStack
  105.     ) {
  106.         $this->urlGenerator $urlGenerator;
  107.         $this->csrfTokenManager $csrfTokenManager;
  108.         $this->securityService $securityService;
  109.         $this->customerService $customerService;
  110.         $this->userService $userService;
  111.         $this->apiService $apiService;
  112.         $this->request $request->getCurrentRequest();
  113.         $this->translator $translator;
  114.         $this->clockService $clockService;
  115.         $this->jsonService $jsonService;
  116.         $this->requestStack $requestStack;
  117.     }
  118.     /**
  119.      * @param Request $request
  120.      *
  121.      * @return bool
  122.      */
  123.     public function supports(Request $request): bool
  124.     {
  125.         //Root is translations and default landing page route
  126.         return in_array($request->attributes->get('_route'), ['app.login''root'])
  127.             && $request->isMethod('POST');
  128.     }
  129.     /**
  130.      * @param Request $request
  131.      *
  132.      * @return array|mixed
  133.      */
  134.     public function getCredentials(Request $request)
  135.     {
  136.         $credentials = [
  137.             'username' => $request->request->get('login')['login'],
  138.             'password' => $request->request->get('login')['password'],
  139.             'twoAuthToken' => $request->request->get('login')['twoAuthToken'] ?? null,
  140.             'csrf_token' => $request->request->get('_csrf_token'),
  141.         ];
  142.         $request->getSession()->set(
  143.             Security::LAST_USERNAME,
  144.             $credentials['username']
  145.         );
  146.         return $credentials;
  147.     }
  148.     /**
  149.      * @param mixed $credentials
  150.      * @param UserProviderInterface $userProvider
  151.      * @param null|array $tokens
  152.      *
  153.      * @throws DecodingExceptionInterface
  154.      *
  155.      * @return null|RedirectResponse|UserInterface
  156.      */
  157.     public function getUser($credentialsUserProviderInterface $userProvider, ?array $tokens null)
  158.     {
  159.         if (null === $tokens) {
  160.             if (isset($credentials['ssoToken'])) {
  161.                 $response $this->securityService->logUserSSO($credentials['ssoToken']);
  162.             } else {
  163.                 $token = new CsrfToken('authenticate'$credentials['csrf_token']);
  164.                 if (!$this->csrfTokenManager->isTokenValid($token)) {
  165.                     throw new InvalidCsrfTokenException();
  166.                 }
  167.                 $options = [
  168.                     'json' => [
  169.                         'username' => $credentials['username'],
  170.                         'password' => $credentials['password'],
  171.                     ],
  172.                 ];
  173.                 if (null !== $credentials['twoAuthToken']) {
  174.                     $options['headers']['TwoAuthToken'] = $credentials['twoAuthToken'];
  175.                 }
  176.                 $response $this->apiService->post('login'$options);
  177.             }
  178.             $loginResponse $response->getArrayResponse();
  179.             if ($loginResponse['error']) {
  180.                 throw new CustomUserMessageAuthenticationException('security.invalid');
  181.             }
  182.             $loginResult $response->getContent();
  183.             $token $loginResult['token'];
  184.             if (null === $token) {
  185.                 if (in_array($loginResult['errorMessage'], [self::ERROR_DISABLEDself::ERROR_EXPIRED])) {
  186.                     throw new CustomUserMessageAuthenticationException('security.disabled');
  187.                 }
  188.                 if (self::ERROR_TWO_AUTH_REQUIRED === $loginResult['errorMessage']) {
  189.                     $credentials['mailError'] = $loginResult['mailError'];
  190.                     throw new CustomUserMessageAuthenticationException('security.twoAuth.required.' mb_strtolower($loginResult['twoAuthType']), $credentials);
  191.                 }
  192.                 throw new CustomUserMessageAuthenticationException('security.invalid');
  193.             }
  194.             $refreshToken $loginResult['refresh_token'];
  195.         } else {
  196.             $token $tokens['token'];
  197.             $refreshToken $tokens['refresh_token'];
  198.         }
  199.         $this->securityService->setToken($token);
  200.         $this->securityService->setRefreshToken($refreshToken);
  201.         $response $this->apiService->get('user/me', [
  202.             'auth_bearer' => $token,
  203.         ]);
  204.         $userResponse $response->getArrayResponse();
  205.         if ($userResponse['error']) {
  206.             throw new CustomUserMessageAuthenticationException('security.invalid');
  207.         }
  208.         $userArray $response->getContent();
  209.         $user = new User();
  210.         $user->setId($userArray['id']);
  211.         $user->setLogin($userArray['login']);
  212.         $user->setTwoFactorAuth($userArray['two_factor_auth']);
  213.         $user->setCustomer($this->jsonService->denormalize(
  214.             $userArray['customer'],
  215.             'App\Object\Admin\Customer'
  216.         ));
  217.         $user->setCustomerType($userArray['customer']['customer_type']);
  218.         $user->setLastPasswordUpdateDate($userArray['last_password_update_date']);
  219.         $user->setRole($this->jsonService->denormalize(
  220.             $userArray['role'],
  221.             'App\Object\Admin\Role'
  222.         ));
  223.         if (!$user) {
  224.             // fail authentication with a custom error
  225.             throw new CustomUserMessageAuthenticationException('Username could not be found.');
  226.         }
  227.         return $user;
  228.     }
  229.     /**
  230.      * @param mixed $credentials
  231.      * @param UserInterface $user
  232.      *
  233.      * @return bool
  234.      */
  235.     public function checkCredentials($credentialsUserInterface $user): bool
  236.     {
  237.         return true;
  238.     }
  239.     /**
  240.      * Used to upgrade (rehash) the user's password automatically over time.
  241.      *
  242.      * @param $credentials
  243.      *
  244.      * @return null|string
  245.      */
  246.     public function getPassword($credentials): ?string
  247.     {
  248.         return $credentials['password'];
  249.     }
  250.     /**
  251.      * @param Request $request
  252.      * @param TokenInterface $token
  253.      * @param string $providerKey
  254.      *
  255.      * @return null|RedirectResponse|Response
  256.      */
  257.     public function onAuthenticationSuccess(Request $requestTokenInterface $tokenstring $providerKey)
  258.     {
  259.         $user $token->getUser();
  260.         $rgpdInformation $this->userService->getRgpdInformation();
  261.         if ($rgpdInformation['isExpired']) {
  262.             return new RedirectResponse(
  263.                 $this->urlGenerator->generate('app.definePassword', [
  264.                     'rgpdOptions' => $rgpdInformation['rgpdOptions'],
  265.                     'login' => $user->getLogin(),
  266.                 ])
  267.             );
  268.         }
  269.         if (null === $user->getTwoFactorAuth() && $rgpdInformation['rgpdOptions']['forceTwoAuth']) {
  270.             $loginInformations $request->request->get('login');
  271.             $session $this->requestStack->getSession();
  272.             //Store in session to get it back after without passing it as request parameters
  273.             $session->set('login-informations'$loginInformations);
  274.             return new RedirectResponse(
  275.                 $this->urlGenerator->generate('app.defineTwoAuth')
  276.             );
  277.         }
  278.         if ($targetPath $this->getTargetPath($request->getSession(), $providerKey)) {
  279.             return new RedirectResponse($targetPath);
  280.         }
  281.         return new RedirectResponse(
  282.             $this->urlGenerator->generate('dashboard.index')
  283.         );
  284.     }
  285.     /**
  286.      * @return string
  287.      */
  288.     protected function getLoginUrl(): string
  289.     {
  290.         return $this->urlGenerator->generate('app.login');
  291.     }
  292. }