<?php
// src/Security/ApiKeyAuthenticator.php
namespace App\Security;
use App\Exception\BadRequestException;
use App\Repository\ApplicationRepository;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
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\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
class AppAuthentificator extends AbstractAuthenticator
{
protected $applicationRepository;
public function __construct(ApplicationRepository $applicationRepository)
{
$this->applicationRepository = $applicationRepository;
}
public function supports(Request $request): ?bool
{
return $request->headers->has('X-CLIENT-ID');
}
public function authenticate(Request $request): Passport
{
$clientId = $request->headers->get('X-CLIENT-ID');
$clientSecret = $request->headers->get('X-CLIENT-SECRET');
$application = $this->applicationRepository->findOneBy(['client_id' => $clientId]);
if (!$application || $application->getClientSecret() !== $clientSecret) {
throw new CustomUserMessageAuthenticationException('Invalid client ID or client secret');
}
try {
JWT::decode($clientSecret, new Key($_ENV["AUTH_SECRET_KEY"], 'HS256'));
} catch (\Exception $e){
throw new BadRequestException('Invalid key: '.$e->getMessage());
}
return new SelfValidatingPassport(new UserBadge($clientId));
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
return null;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
$data = [
'message' => strtr($exception->getMessageKey(), $exception->getMessageData())
];
return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);
}
}