src/App/Controller/API/AuthController.php line 254

  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controller\API;
  4. use API\Exception\ValidationException;
  5. use App\DTO\APIRequest\AuthDTO;
  6. use App\DTO\Auth\AuthJWTResponse;
  7. use App\DTO\Auth\AuthUserRawData;
  8. use App\Entity\Users;
  9. use App\Security\EmailAuthenticator;
  10. use App\Security\FacebookSignedRequestAuthenticator;
  11. use App\Security\GoogleOAuth2Authenticator;
  12. use App\Service\User\UserLoginService;
  13. use App\Service\User\UsersManagementService;
  14. use Doctrine\ORM\EntityManagerInterface;
  15. use Exception;
  16. use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
  17. use KnpU\OAuth2ClientBundle\Client\Provider\FacebookClient;
  18. use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
  19. use League\OAuth2\Client\Token\AccessToken;
  20. use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
  21. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  22. use Symfony\Component\HttpFoundation\JsonResponse;
  23. use Symfony\Component\HttpFoundation\Request;
  24. use Symfony\Component\HttpFoundation\Response;
  25. use Symfony\Component\Routing\Attribute\Route;
  26. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  27. #[Route(path"/auth")]
  28. final class AuthController extends AbstractController
  29. {
  30.     public function __construct(
  31.         private readonly EntityManagerInterface $em,
  32.         private readonly UserLoginService $userLoginService
  33.     )
  34.     {
  35.     }
  36.     #[Route(path"/facebook/verify"methods: ["GET"], name"api.auth.facebook.check")]
  37.     public function getAuthFacebookCheck(
  38.         Request $request,
  39.         ClientRegistry $clientRegistry,
  40.         JWTTokenManagerInterface $jwt,
  41.         UsersManagementService $usersManagementService,
  42.         EntityManagerInterface $em,
  43.     ) {
  44.         $accessToken $request->get('access_token');
  45.         /** @var FacebookClient $client */
  46.         $client $clientRegistry->getClient('facebook_main');
  47.         try {
  48.             $t = new AccessToken(
  49.                 [
  50.                     'access_token' => $accessToken,
  51.                 ]
  52.             );
  53.             $facebookUser $client->fetchUserFromToken($t);
  54.         } catch (IdentityProviderException $e) {
  55.             return $this->json(
  56.                 new AuthJWTResponse(
  57.                     AuthJWTResponse::STATUS_ERROR,
  58.                     null,
  59.                     $e->getMessage()
  60.                 ),
  61.                 Response::HTTP_FORBIDDEN
  62.             );
  63.         }
  64.         /** @var Users $user */
  65.         $user $this
  66.             ->em
  67.             ->getRepository(Users::class)
  68.             ->findByFacebook($facebookUser->getId());
  69.         if (!$user) {
  70.             $authUserRawData = (new AuthUserRawData())
  71.                 ->setIdentity($facebookUser->getId())
  72.                 ->setFirstName($facebookUser->getFirstName())
  73.                 ->setLastName($facebookUser->getLastName())
  74.                 ->setAvatar($facebookUser->getPictureUrl())
  75.                 ->setLanguage($request->getLocale());
  76.             $user $usersManagementService->createUser(Users::AUTH_FB$authUserRawData$this->getUser());
  77.         } else {
  78.             try {
  79.                 $avatar $facebookUser->getPictureUrl();
  80.                 if (!empty($avatar)) {
  81.                     $user->getUserData()->setPicture($avatar);
  82.                     $em->flush();
  83.                 }
  84.             } catch (\Throwable $e) {
  85.             }
  86.         }
  87.         $token $jwt->create($user);
  88.         return $this->json(
  89.             new AuthJWTResponse(
  90.                 AuthJWTResponse::STATUS_SUCCESS,
  91.                 $token
  92.             )
  93.         );
  94.     }
  95.     #[Route(path"/apple/verify"methods: ["GET"], name"api.auth.apple.check")]
  96.     public function getAuthAppleCheck(
  97.         Request $request,
  98.         ClientRegistry $clientRegistry,
  99.         JWTTokenManagerInterface $jwt,
  100.         UsersManagementService $usersManagementService
  101.     ) {
  102.         $accessToken $request->get('access_token');
  103.         $code $request->get('code');
  104.         $firstName = (string)$request->get('first_name');
  105.         $lastName = (string)$request->get('last_name');
  106.         try {
  107.             $appleUser $usersManagementService->decodeAppleAccessToken($accessToken);
  108.         } catch (Exception $e) {
  109.             return $this->json(
  110.                 new AuthJWTResponse(
  111.                     AuthJWTResponse::STATUS_ERROR,
  112.                     null,
  113.                     $e->getMessage()
  114.                 ),
  115.                 Response::HTTP_FORBIDDEN
  116.             );
  117.         }
  118.         /** @var Users $user */
  119.         $user $this
  120.             ->em
  121.             ->getRepository(Users::class)
  122.             ->findByApple($appleUser['id']);
  123.         if (!$user) {
  124.             $authUserRawData = (new AuthUserRawData())
  125.                 ->setIdentity($appleUser['id'])
  126.                 ->setEmail($appleUser['email'])
  127.                 ->setFirstName($firstName)
  128.                 ->setLastName($lastName);
  129.             $user $usersManagementService->createUser(Users::AUTH_APPLE$authUserRawData$this->getUser());
  130.         }
  131.         $token $jwt->create($user);
  132.         return $this->json(
  133.             new AuthJWTResponse(
  134.                 AuthJWTResponse::STATUS_SUCCESS,
  135.                 $token
  136.             )
  137.         );
  138.     }
  139.     #[Route(path"/google/verify"methods: ["GET"], name"api.auth.google.check")]
  140.     public function getAuthGoogleCheck(
  141.         Request $request,
  142.         ClientRegistry $clientRegistry,
  143.         JWTTokenManagerInterface $jwt,
  144.         UsersManagementService $usersManagementService
  145.     ) {
  146.         $accessToken $request->get('access_token');
  147.         try {
  148.             $googleUser $usersManagementService->decodeGoogleAccessToken($accessToken);
  149.         } catch (Exception $e) {
  150.             return $this->json(
  151.                 new AuthJWTResponse(
  152.                     AuthJWTResponse::STATUS_ERROR,
  153.                     null,
  154.                     $e->getMessage()
  155.                 ),
  156.                 Response::HTTP_FORBIDDEN
  157.             );
  158.         }
  159.         // $identity $googleUser['id']
  160.         $identity $googleUser['email'];
  161.         /** @var Users $user */
  162.         $user $this
  163.             ->em
  164.             ->getRepository(Users::class)
  165.             ->findByGoogle($identity);
  166.         if (!$user) {
  167.             $authUserRawData = (new AuthUserRawData())
  168.                 ->setIdentity($identity)
  169.                 ->setEmail($googleUser['email'])
  170.                 ->setFirstName($googleUser['first_name'])
  171.                 ->setLastName($googleUser['last_name'])
  172.                 ->setAvatar($googleUser['picture'])
  173.                 ->setLanguage($googleUser['locale']);
  174.             $user $usersManagementService->createUser(Users::AUTH_GOOGLE$authUserRawData$this->getUser());
  175.         }
  176.         $token $jwt->create($user);
  177.         return $this->json(
  178.             new AuthJWTResponse(
  179.                 AuthJWTResponse::STATUS_SUCCESS,
  180.                 $token
  181.             )
  182.         );
  183.     }
  184.     #[Route(path"/huawei/verify"methods: ["GET"])]
  185.     public function getAuthHuaweiCheck(
  186.         Request $request,
  187.         ClientRegistry $clientRegistry,
  188.         JWTTokenManagerInterface $jwt,
  189.         UsersManagementService $usersManagementService
  190.     ) {
  191.         $accessToken $request->get('access_token');
  192.         try {
  193.             $huaweiUser $usersManagementService->decodeHuaweiAccessToken($accessToken);
  194.         } catch (Exception $e) {
  195.             return $this->json(
  196.                 new AuthJWTResponse(
  197.                     AuthJWTResponse::STATUS_ERROR,
  198.                     null,
  199.                     $e->getMessage()
  200.                 ),
  201.                 Response::HTTP_FORBIDDEN
  202.             );
  203.         }
  204.         // $identity $googleUser['id']
  205.         $identity $huaweiUser['id'];
  206.         /** @var Users $user */
  207.         $user $this
  208.             ->em
  209.             ->getRepository(Users::class)
  210.             ->findByHuawei($identity);
  211.         if (!$user) {
  212.             $authUserRawData = (new AuthUserRawData())
  213.                 ->setIdentity($identity)
  214.                 ->setEmail($huaweiUser['id']."@huawei.com")
  215.                 ->setFirstName($huaweiUser['first_name'])
  216.                 ->setLastName($huaweiUser['last_name'])
  217.                 ->setLanguage($huaweiUser['locale']);
  218.             $user $usersManagementService->createUser(Users::AUTH_HUAWEI$authUserRawData$this->getUser());
  219.         }
  220.         $token $jwt->create($user);
  221.         return $this->json(
  222.             new AuthJWTResponse(
  223.                 AuthJWTResponse::STATUS_SUCCESS,
  224.                 $token
  225.             )
  226.         );
  227.     }
  228.     #[Route(path"/guest"methods: ["GET"])]
  229.     public function getAuthGuest(
  230.         Request $request,
  231.         JWTTokenManagerInterface $jwt,
  232.         UsersManagementService $usersManagementService
  233.     ): JsonResponse {
  234.         $deviceIdentity $request->get('device_identity');
  235.         if ($deviceIdentity) {
  236.             $user $usersManagementService->findOrCreateGuestUserByDeviceIdentity($deviceIdentity);
  237.         } else {
  238.             $user $usersManagementService->createGuestUser();
  239.         }
  240.         $token $jwt->create($user);
  241.         return $this->json(
  242.             new AuthJWTResponse(
  243.                 AuthJWTResponse::STATUS_SUCCESS,
  244.                 $token
  245.             )
  246.         );
  247.     }
  248.     #[Route(path""methods: ["POST"])]
  249.     public function auth(
  250.         AuthDTO $requestDTO,
  251.         Request $request,
  252.         JWTTokenManagerInterface $jwt,
  253.         GoogleOAuth2Authenticator $googleOAuth2Authenticator,
  254.         FacebookSignedRequestAuthenticator $facebookAuthenticator,
  255.         EmailAuthenticator $emailAuthenticator
  256.     ): AuthJWTResponse
  257.     {
  258.         $request->request->set('type'$requestDTO->type);
  259.         $request->request->set('token'$requestDTO->token);
  260.         $request->request->set('email'$requestDTO->email);
  261.         $request->request->set('password'$requestDTO->password);
  262.         try {
  263.             $passport = match ($requestDTO->type) {
  264.                 'email' => $emailAuthenticator->authenticate($request),
  265.                 'google' => $googleOAuth2Authenticator->authenticate($request),
  266.                 'facebook' => $facebookAuthenticator->authenticate($request),
  267.                 default => throw new AuthenticationException('Invalid type')
  268.             };
  269.         } catch (AuthenticationException $e) {
  270.             match ($requestDTO->type) {
  271.                 'email' => throw ValidationException::violation('Invalid email or password'$requestDTO->email'email'),
  272.                 default =>throw ValidationException::violation('Invalid credentials'$requestDTO->token'token')
  273.             };
  274.         }
  275.         $user $passport->getUser();
  276.         if (!$user instanceof Users) {
  277.             throw $this->createAccessDeniedException();
  278.         }
  279.         $token $jwt->create($user);
  280.         $this->userLoginService->callLoginRoutines($user$request);
  281.         return new AuthJWTResponse(
  282.             AuthJWTResponse::STATUS_SUCCESS,
  283.             $token
  284.         );
  285.     }
  286. }