<?php
declare(strict_types=1);
namespace Slivki\Security;
use Slivki\Entity\User;
use Slivki\Exception\User\InvalidUserTokenException;
use Slivki\Repository\User\UserRepositoryInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
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;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use Symfony\Component\Security\Core\Security;
final class SlivkiAuthenticator extends AbstractAuthenticator implements AuthenticationEntryPointInterface
{
public const USER_COOKIE = 'visitedoffers4';
private UserRepositoryInterface $userRepository;
private HttpUtils $httpUtils;
private Security $security;
public function __construct(
UserRepositoryInterface $userRepository,
HttpUtils $httpUtils,
Security $security
) {
$this->userRepository = $userRepository;
$this->httpUtils = $httpUtils;
$this->security = $security;
}
public function supports(Request $request): ?bool
{
return $request->cookies->has(self::USER_COOKIE) && !($this->security->getToken() instanceof SwitchUserToken);
}
public function authenticate(Request $request): PassportInterface
{
$userToken = $request->cookies->get(self::USER_COOKIE);
if (null === $userToken) {
throw new InvalidUserTokenException();
}
return new SelfValidatingPassport(
new UserBadge($userToken, fn (): ?User => $this->userRepository->findByToken((string) $userToken)),
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
return null;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
return $this->httpUtils->createRedirectResponse($request, 'login', Response::HTTP_FOUND);
}
public function start(Request $request, AuthenticationException $authException = null): Response
{
return $this->httpUtils->createRedirectResponse($request, 'login', Response::HTTP_FOUND);
}
}