src/Security/TokenAuthenticator.php line 66

Open in your IDE?
  1. <?php
  2. namespace App\Security;
  3. use App\Repository\UserRepository;
  4. use App\Utils\UserUtils;
  5. use Doctrine\ORM\EntityManagerInterface;
  6. use Evo\Infrastructure\MappingORM\User;
  7. use Symfony\Component\HttpFoundation\JsonResponse;
  8. use Symfony\Component\HttpFoundation\Request;
  9. use Symfony\Component\HttpFoundation\Response;
  10. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  11. use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  12. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  13. use Symfony\Component\Security\Core\Security;
  14. use Symfony\Component\Security\Core\User\UserInterface;
  15. use Symfony\Component\Security\Core\User\UserProviderInterface;
  16. use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
  17. class TokenAuthenticator extends AbstractGuardAuthenticator
  18. {
  19.     private const ROUTE_NAME 'api_auth';
  20.     private EntityManagerInterface $em;
  21.     private UserPasswordEncoderInterface $passwordEncoder;
  22.     private UserUtils $userUtils;
  23.     private Security $security;
  24.     public function __construct(EntityManagerInterface $emUserPasswordEncoderInterface $passwordEncoderUserUtils $userUtilsSecurity $security)
  25.     {
  26.         $this->em $em;
  27.         $this->passwordEncoder $passwordEncoder;
  28.         $this->userUtils $userUtils;
  29.         $this->security $security;
  30.     }
  31.     /**
  32.      * Called on every request to decide if this authenticator should be
  33.      * used for the request. Returning `false` will cause this authenticator
  34.      * to be skipped.
  35.      */
  36.     public function supports(Request $request): bool
  37.     {
  38.         return self::ROUTE_NAME === $request->attributes->get('_route') && 'POST' === $request->getMethod();
  39.     }
  40.     /**
  41.      * Called on every request. Return whatever credentials you want to
  42.      * be passed to getUser() as $credentials.
  43.      */
  44.     public function getCredentials(Request $request)
  45.     {
  46.         $body json_decode($request->getContent(), null512JSON_THROW_ON_ERROR);
  47.         if (null === $body) {
  48.             return [];
  49.         }
  50.         $credentials = [
  51.             'username' => $body->username,
  52.             'password' => $body->password,
  53.         ];
  54.         $request->getSession()->set(
  55.             Security::LAST_USERNAME,
  56.             $credentials['username']
  57.         );
  58.         return $credentials;
  59.     }
  60.     public function getUser($credentialsUserProviderInterface $userProvider): ?UserInterface
  61.     {
  62.         if (empty($credentials)) {
  63.             // The token header was empty, authentication fails with HTTP Status
  64.             // Code 401 "Unauthorized"
  65.             return null;
  66.         }
  67.         // The user identifier in this case is the apiToken, see the key `property`
  68.         // of `your_db_provider` in `security.yaml`.
  69.         // If this returns a user, checkCredentials() is called next:
  70.         /** @var UserRepository $userRepository */
  71.         $userRepository $this->em->getRepository(User::class);
  72.         return $userRepository->loadUserByUsername($credentials['username'], true);
  73.     }
  74.     public function checkCredentials($credentialsUserInterface $user): bool
  75.     {
  76.         return $this->passwordEncoder->isPasswordValid($user$credentials['password']);
  77.     }
  78.     public function onAuthenticationFailure(Request $requestAuthenticationException $exception): ?Response
  79.     {
  80.         $data = [
  81.             // you may want to customize or obfuscate the message first
  82.             'message' => strtr($exception->getMessageKey(), $exception->getMessageData()),
  83.             // or to translate this message
  84.             // $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())
  85.         ];
  86.         $data['message'] .= ' Or your user is deactivated';
  87.         return new JsonResponse($dataResponse::HTTP_UNAUTHORIZED);
  88.     }
  89.     /**
  90.      * Called when authentication is needed, but it's not sent.
  91.      */
  92.     public function start(Request $requestAuthenticationException $authException null): Response
  93.     {
  94.         $data = [
  95.             // you might translate this message
  96.             'message' => 'Authentication Required',
  97.         ];
  98.         return new JsonResponse($dataResponse::HTTP_UNAUTHORIZED);
  99.     }
  100.     public function supportsRememberMe(): bool
  101.     {
  102.         return false;
  103.     }
  104.     public function onAuthenticationSuccess(Request $requestTokenInterface $token$providerKey)
  105.     {
  106.         if ($request->query->get('da')) {
  107.             $code $this->userUtils->generateCodeConfirmation();
  108.             /** @var User $user */
  109.             $user $this->security->getUser();
  110.             $user->setCodeConfirmation($code);
  111.             $this->em->persist($user);
  112.             $this->em->flush();
  113.         }
  114.         return null;
  115.     }
  116. }