<?php
namespace App\Security;
use App\Entity\Painel\Api;
use App\Repository\Painel\ClienteRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
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\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ApiAuthenticator extends AbstractGuardAuthenticator
{
private $em;
private $container;
private $security;
private $clienteRepository;
public function __construct(
EntityManagerInterface $em,
Security $security,
ContainerInterface $container,
ClienteRepository $clienteRepository
)
{
$this->em = $em;
$this->security = $security;
$this->container = $container;
$this->clienteRepository = $clienteRepository;
}
/**
* Called on every request to decide if this authenticator should be
* used for the request. Returning `false` will cause this authenticator
* to be skipped.
*/
public function supports(Request $request): bool
{
if($request->getMethod() == 'OPTIONS') {
return true;
}
return $request->headers->has('X-AUTH-CREDENCIAL') && $request->headers->has('X-AUTH-TOKEN');
}
/**
* Called on every request. Return whatever credentials you want to
* be passed to getUser() as $credentials.
*/
public function getCredentials(Request $request)
{
if($request->getMethod() == 'OPTIONS') {
return true;
}
return ['credencial' => $request->headers->get('X-AUTH-CREDENCIAL'), 'token' => $request->headers->get('X-AUTH-TOKEN')];
}
public function getUser($credentials, UserProviderInterface $userProvider): ?UserInterface
{
if($this->container->get('request_stack')->getCurrentRequest()->getMethod() == 'OPTIONS') {
return $this->em->getRepository(Api::class)->find(1);
}
if (null === $credentials) {
// The token header was empty, authentication fails with HTTP Status
// Code 401 "Unauthorized"
return null;
}
$this->user = $this->em->getRepository(Api::class)->findOneBy($credentials);
// The "username" in this case is the apiToken, see the key `property`
// of `your_db_provider` in `security.yaml`.
// If this returns a user, checkCredentials() is called next:
return $this->em->getRepository(Api::class)->findOneBy($credentials);
}
public function checkCredentials($credentials, UserInterface $user): bool
{
// Check credentials - e.g. make sure the password is valid.
// In case of an API token, no credential check is needed.
// Return `true` to cause authentication success
return true;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey): ?Response
{
if($request->getMethod() == 'OPTIONS') {
return null;
}
$idCliente = $token->getUser()->getIdCliente();
$cliente = $this->clienteRepository->find($idCliente);
$this->container->get('doctrine.dbal.cliente_connection')->forceSwitch($cliente->getDbname(), $cliente->getHost());
return null;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
$data = [
// you may want to customize or obfuscate the message first
'message' => 'Falha na autenticação. Verifique as credenciais no 2iM.DW - Painel.'
// or to translate this message
// $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())
];
return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);
}
/**
* Called when authentication is needed, but it's not sent
*/
public function start(Request $request, AuthenticationException $authException = null): Response
{
if($request->getMethod() == 'OPTIONS') {
return true;
}
$data = [
// you might translate this message
'message' => 'Autenticação Obrigatória.'
];
return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);
}
public function supportsRememberMe(): bool
{
return false;
}
}