<?php
namespace App\Security;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectRepository;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
class SelfValidationAuthenticator extends AbstractAuthenticator
{
private UrlGeneratorInterface $urlGenerator;
private ObjectRepository $userRepository;
public function __construct(UrlGeneratorInterface $urlGenerator, EntityManagerInterface $entityManager)
{
$this->urlGenerator = $urlGenerator;
$this->userRepository = $entityManager->getRepository(User::class);
}
public function supports(Request $request): ?bool
{
return $request->isMethod('GET') &&
$this->urlGenerator->generate('self_validating_authentication') === $request->getPathInfo() &&
$request->getSession()->has('self_validating_authentication_options');
}
public function authenticate(Request $request): PassportInterface
{
$user = $this->getUser($request);
return new SelfValidatingPassport(
new UserBadge($user->getEmail())
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
return new RedirectResponse($this->urlGenerator->generate($this->getRedirectPath($request)));
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
return null;
}
private function getOptions(Request $request): array
{
return $request->getSession()->get('self_validating_authentication_options');
}
private function getRedirectPath(Request $request): string
{
return $this->getOptions($request)['redirect_to'];
}
private function getUserId(Request $request): string
{
return $this->getOptions($request)['user_id'];
}
private function getUser(Request $request): User
{
return $this->userRepository->find($this->getUserId($request));
}
}