src/EventSubscriber/PublicRouteBearerTokenSubscriber.php line 31

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  4. use Symfony\Component\HttpFoundation\Request;
  5. use Symfony\Component\HttpKernel\Event\RequestEvent;
  6. use Symfony\Component\HttpKernel\KernelEvents;
  7. use Symfony\Component\Security\Http\AccessMapInterface;
  8. /**
  9.  * Public API routes must stay accessible even when clients send an expired Bearer JWT.
  10.  * The api firewall validates JWT before access_control runs; stripping Bearer on public
  11.  * routes prevents Lexik from rejecting the request. Basic Auth headers are preserved.
  12.  */
  13. final class PublicRouteBearerTokenSubscriber implements EventSubscriberInterface
  14. {
  15.     public function __construct(
  16.         private readonly AccessMapInterface $accessMap,
  17.     ) {
  18.     }
  19.     public static function getSubscribedEvents(): array
  20.     {
  21.         return [
  22.             // Run before Symfony FirewallListener (priority 8).
  23.             KernelEvents::REQUEST => ['onKernelRequest'9],
  24.         ];
  25.     }
  26.     public function onKernelRequest(RequestEvent $event): void
  27.     {
  28.         if (!$event->isMainRequest()) {
  29.             return;
  30.         }
  31.         $request $event->getRequest();
  32.         if (!$this->isPublicApiRoute($request)) {
  33.             return;
  34.         }
  35.         $authHeader $request->headers->get('Authorization');
  36.         if ($authHeader !== null && str_starts_with($authHeader'Bearer ')) {
  37.             $request->headers->remove('Authorization');
  38.         }
  39.     }
  40.     private function isPublicApiRoute(Request $request): bool
  41.     {
  42.         if (!str_starts_with($request->getPathInfo(), '/api/')) {
  43.             return false;
  44.         }
  45.         [$attributes] = $this->accessMap->getPatterns($request);
  46.         return \in_array('PUBLIC_ACCESS'$attributestrue);
  47.     }
  48. }