src/App/Controller/API/AuthController.php line 254
<?php
declare(strict_types=1);
namespace App\Controller\API;
use API\Exception\ValidationException;
use App\DTO\APIRequest\AuthDTO;
use App\DTO\Auth\AuthJWTResponse;
use App\DTO\Auth\AuthUserRawData;
use App\Entity\Users;
use App\Security\EmailAuthenticator;
use App\Security\FacebookSignedRequestAuthenticator;
use App\Security\GoogleOAuth2Authenticator;
use App\Service\User\UserLoginService;
use App\Service\User\UsersManagementService;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use KnpU\OAuth2ClientBundle\Client\Provider\FacebookClient;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Token\AccessToken;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
#[Route(path: "/auth")]
final class AuthController extends AbstractController
{
public function __construct(
private readonly EntityManagerInterface $em,
private readonly UserLoginService $userLoginService
)
{
}
#[Route(path: "/facebook/verify", methods: ["GET"], name: "api.auth.facebook.check")]
public function getAuthFacebookCheck(
Request $request,
ClientRegistry $clientRegistry,
JWTTokenManagerInterface $jwt,
UsersManagementService $usersManagementService,
EntityManagerInterface $em,
) {
$accessToken = $request->get('access_token');
/** @var FacebookClient $client */
$client = $clientRegistry->getClient('facebook_main');
try {
$t = new AccessToken(
[
'access_token' => $accessToken,
]
);
$facebookUser = $client->fetchUserFromToken($t);
} catch (IdentityProviderException $e) {
return $this->json(
new AuthJWTResponse(
AuthJWTResponse::STATUS_ERROR,
null,
$e->getMessage()
),
Response::HTTP_FORBIDDEN
);
}
/** @var Users $user */
$user = $this
->em
->getRepository(Users::class)
->findByFacebook($facebookUser->getId());
if (!$user) {
$authUserRawData = (new AuthUserRawData())
->setIdentity($facebookUser->getId())
->setFirstName($facebookUser->getFirstName())
->setLastName($facebookUser->getLastName())
->setAvatar($facebookUser->getPictureUrl())
->setLanguage($request->getLocale());
$user = $usersManagementService->createUser(Users::AUTH_FB, $authUserRawData, $this->getUser());
} else {
try {
$avatar = $facebookUser->getPictureUrl();
if (!empty($avatar)) {
$user->getUserData()->setPicture($avatar);
$em->flush();
}
} catch (\Throwable $e) {
}
}
$token = $jwt->create($user);
return $this->json(
new AuthJWTResponse(
AuthJWTResponse::STATUS_SUCCESS,
$token
)
);
}
#[Route(path: "/apple/verify", methods: ["GET"], name: "api.auth.apple.check")]
public function getAuthAppleCheck(
Request $request,
ClientRegistry $clientRegistry,
JWTTokenManagerInterface $jwt,
UsersManagementService $usersManagementService
) {
$accessToken = $request->get('access_token');
$code = $request->get('code');
$firstName = (string)$request->get('first_name');
$lastName = (string)$request->get('last_name');
try {
$appleUser = $usersManagementService->decodeAppleAccessToken($accessToken);
} catch (Exception $e) {
return $this->json(
new AuthJWTResponse(
AuthJWTResponse::STATUS_ERROR,
null,
$e->getMessage()
),
Response::HTTP_FORBIDDEN
);
}
/** @var Users $user */
$user = $this
->em
->getRepository(Users::class)
->findByApple($appleUser['id']);
if (!$user) {
$authUserRawData = (new AuthUserRawData())
->setIdentity($appleUser['id'])
->setEmail($appleUser['email'])
->setFirstName($firstName)
->setLastName($lastName);
$user = $usersManagementService->createUser(Users::AUTH_APPLE, $authUserRawData, $this->getUser());
}
$token = $jwt->create($user);
return $this->json(
new AuthJWTResponse(
AuthJWTResponse::STATUS_SUCCESS,
$token
)
);
}
#[Route(path: "/google/verify", methods: ["GET"], name: "api.auth.google.check")]
public function getAuthGoogleCheck(
Request $request,
ClientRegistry $clientRegistry,
JWTTokenManagerInterface $jwt,
UsersManagementService $usersManagementService
) {
$accessToken = $request->get('access_token');
try {
$googleUser = $usersManagementService->decodeGoogleAccessToken($accessToken);
} catch (Exception $e) {
return $this->json(
new AuthJWTResponse(
AuthJWTResponse::STATUS_ERROR,
null,
$e->getMessage()
),
Response::HTTP_FORBIDDEN
);
}
// $identity $googleUser['id']
$identity = $googleUser['email'];
/** @var Users $user */
$user = $this
->em
->getRepository(Users::class)
->findByGoogle($identity);
if (!$user) {
$authUserRawData = (new AuthUserRawData())
->setIdentity($identity)
->setEmail($googleUser['email'])
->setFirstName($googleUser['first_name'])
->setLastName($googleUser['last_name'])
->setAvatar($googleUser['picture'])
->setLanguage($googleUser['locale']);
$user = $usersManagementService->createUser(Users::AUTH_GOOGLE, $authUserRawData, $this->getUser());
}
$token = $jwt->create($user);
return $this->json(
new AuthJWTResponse(
AuthJWTResponse::STATUS_SUCCESS,
$token
)
);
}
#[Route(path: "/huawei/verify", methods: ["GET"])]
public function getAuthHuaweiCheck(
Request $request,
ClientRegistry $clientRegistry,
JWTTokenManagerInterface $jwt,
UsersManagementService $usersManagementService
) {
$accessToken = $request->get('access_token');
try {
$huaweiUser = $usersManagementService->decodeHuaweiAccessToken($accessToken);
} catch (Exception $e) {
return $this->json(
new AuthJWTResponse(
AuthJWTResponse::STATUS_ERROR,
null,
$e->getMessage()
),
Response::HTTP_FORBIDDEN
);
}
// $identity $googleUser['id']
$identity = $huaweiUser['id'];
/** @var Users $user */
$user = $this
->em
->getRepository(Users::class)
->findByHuawei($identity);
if (!$user) {
$authUserRawData = (new AuthUserRawData())
->setIdentity($identity)
->setEmail($huaweiUser['id']."@huawei.com")
->setFirstName($huaweiUser['first_name'])
->setLastName($huaweiUser['last_name'])
->setLanguage($huaweiUser['locale']);
$user = $usersManagementService->createUser(Users::AUTH_HUAWEI, $authUserRawData, $this->getUser());
}
$token = $jwt->create($user);
return $this->json(
new AuthJWTResponse(
AuthJWTResponse::STATUS_SUCCESS,
$token
)
);
}
#[Route(path: "/guest", methods: ["GET"])]
public function getAuthGuest(
Request $request,
JWTTokenManagerInterface $jwt,
UsersManagementService $usersManagementService
): JsonResponse {
$deviceIdentity = $request->get('device_identity');
if ($deviceIdentity) {
$user = $usersManagementService->findOrCreateGuestUserByDeviceIdentity($deviceIdentity);
} else {
$user = $usersManagementService->createGuestUser();
}
$token = $jwt->create($user);
return $this->json(
new AuthJWTResponse(
AuthJWTResponse::STATUS_SUCCESS,
$token
)
);
}
#[Route(path: "", methods: ["POST"])]
public function auth(
AuthDTO $requestDTO,
Request $request,
JWTTokenManagerInterface $jwt,
GoogleOAuth2Authenticator $googleOAuth2Authenticator,
FacebookSignedRequestAuthenticator $facebookAuthenticator,
EmailAuthenticator $emailAuthenticator
): AuthJWTResponse
{
$request->request->set('type', $requestDTO->type);
$request->request->set('token', $requestDTO->token);
$request->request->set('email', $requestDTO->email);
$request->request->set('password', $requestDTO->password);
try {
$passport = match ($requestDTO->type) {
'email' => $emailAuthenticator->authenticate($request),
'google' => $googleOAuth2Authenticator->authenticate($request),
'facebook' => $facebookAuthenticator->authenticate($request),
default => throw new AuthenticationException('Invalid type')
};
} catch (AuthenticationException $e) {
match ($requestDTO->type) {
'email' => throw ValidationException::violation('Invalid email or password', $requestDTO->email, 'email'),
default =>throw ValidationException::violation('Invalid credentials', $requestDTO->token, 'token')
};
}
$user = $passport->getUser();
if (!$user instanceof Users) {
throw $this->createAccessDeniedException();
}
$token = $jwt->create($user);
$this->userLoginService->callLoginRoutines($user, $request);
return new AuthJWTResponse(
AuthJWTResponse::STATUS_SUCCESS,
$token
);
}
}