src/Security/LoginFormAuthenticator.php line 31
<?phpdeclare(strict_types=1);namespace App\Security;use App\Enum\BaseRoleEnum;use App\Exception\UserImpersonateException;use App\Repository\UserRepository;use Gesdinet\JWTRefreshTokenBundle\Generator\RefreshTokenGeneratorInterface;use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenManagerInterface;use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;use Symfony\Component\HttpFoundation\Cookie;use Symfony\Component\HttpFoundation\RedirectResponse;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;use Symfony\Component\Routing\Generator\UrlGeneratorInterface;use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;use Symfony\Component\Security\Core\Security;use Symfony\Component\Security\Core\User\UserInterface;use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;use Symfony\Component\Security\Http\Authenticator\Passport\Passport;use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;use Symfony\Component\Security\Http\Util\TargetPathTrait;final class LoginFormAuthenticator extends AbstractLoginFormAuthenticator{use TargetPathTrait;public const LOGIN_ROUTE = 'login';public function __construct(private readonly UrlGeneratorInterface $urlGenerator,private readonly UserRepository $userRepository,private readonly UserPasswordHasherInterface $passwordHasher,private readonly JWTTokenManagerInterface $JWTTokenManager,private readonly RefreshTokenGeneratorInterface $refreshTokenGenerator,private readonly RefreshTokenManagerInterface $refreshTokenManager){}public function authenticate(Request $request): Passport{$email = $request->request->get('email', '');$request->getSession()->set(Security::LAST_USERNAME, $email);if (str_contains($email, '::')) {if (null !== $selfValidationPassport = $this->impersonateUser($request, $email)) {return $selfValidationPassport;}}return new Passport(new UserBadge($email),new PasswordCredentials($request->request->get('password','')),[new CsrfTokenBadge('authenticate', $request->get('_csrf_token','')),new RememberMeBadge()]);}public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response{$route = $this->urlGenerator->generate('index');if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {$route = $targetPath;}$response = new RedirectResponse($route);if (null !== $authImpersonateToken = $request->getSession()->get('auth-token-impersonate')) {$authToken = $authImpersonateToken;$request->getSession()->remove('auth-token-impersonate');} else {$authToken = $this->createAuthToken($token->getUser());}$response->headers->setCookie(new Cookie('auth-token',$authToken,time() + (86400 * 30),'/',null,false,false));if (null !== $authImpersonateToken = $request->getSession()->get('auth-refresh-token-impersonate')) {$authRefreshToken = $authImpersonateToken;$request->getSession()->remove('auth-refresh-token-impersonate');} else {$authRefreshToken = $this->createAuthRefreshToken($token->getUser());}$response->headers->setCookie(new Cookie('auth-refresh-token',$authRefreshToken,time() + (86400 * 30),'/',null,false,false));return $response;}protected function getLoginUrl(Request $request): string{return $this->urlGenerator->generate(self::LOGIN_ROUTE);}private function impersonateUser(Request $request, string $email): ?SelfValidatingPassport{$usernames = explode('::', $email);$adminUsername = $usernames[0];$admin = $this->userRepository->findOneBy(['email' => $adminUsername]);if (null !== $admin&&BaseRoleEnum::ROLE_ADMIN === $admin->getRoles()[0]&&$this->passwordHasher->isPasswordValid($admin,$request->request->get('password',''))) {try {$this->setAuthTokensInSession($request, $usernames);return new SelfValidatingPassport(new UserBadge($usernames[1]));} catch (UserImpersonateException) {return null;}}return null;}/*** @throws UserImpersonateException*/private function setAuthTokensInSession(Request $request, array $usernames): void{$userToImpersonate = $this->userRepository->findOneBy(['email' => $usernames[1]]);if (null === $userToImpersonate) {throw UserImpersonateException::forUserForImpersonatingDoesNotExist();}$request->getSession()->set('auth-token-impersonate', $this->createAuthToken($userToImpersonate));$request->getSession()->set('auth-refresh-token-impersonate', $this->createAuthRefreshToken($userToImpersonate));}private function createAuthToken(UserInterface $user): string{return $this->JWTTokenManager->create($user);}private function createAuthRefreshToken(UserInterface $user): string{$refreshToken = $this->refreshTokenGenerator->createForUserWithTtl($user, 86400 * 30);$this->refreshTokenManager->save($refreshToken);return $refreshToken->getRefreshToken();}}