src/AppBundle/EventSubscriber/TokenSubscriber.php line 70

Open in your IDE?
  1. <?php
  2. namespace AppBundle\EventSubscriber;
  3. use AppBundle\Controller\ui\TokenAuthenticatedController;
  4. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  5. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  6. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  7. use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
  8. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  9. use Symfony\Component\HttpKernel\KernelEvents;
  10. use Symfony\Component\HttpFoundation\RedirectResponse;
  11. use Psr\Log\LoggerInterface;
  12. use AppBundle\Security\ApiKeyUserProvider;
  13. use AppBundle\Service\OAuthHelper;
  14. use AppBundle\CSPro\CSProResponse;
  15. use Symfony\Component\HttpFoundation\Request;
  16. //checks if the access token is available before handling a request
  17. class TokenSubscriber implements EventSubscriberInterface {
  18.     public function __construct(private ApiKeyUserProvider $apikeyUserProvider, private UrlGeneratorInterface $router, private TokenStorageInterface $tokenStorage,  private OAuthHelper $oauthServicestring $timeZone, private LoggerInterface $logger) {
  19.         // Set default timezone to avoid warnings when using date/time functions 
  20.         // and timezone not set in php.ini
  21.        date_default_timezone_set($timeZone);
  22.     }
  23.     public function verifyResourceRequest(Request $request) {
  24.         // ...  
  25.         //getContent becomes empty when doing verifyResourceRequest check in the before event  on PUT requests 
  26.         //one way to avoid is to remove this check on PUT requests before events. 
  27.         //alternative is to call the getContent  on PUT requests. If this sttops working remove the before event and figure out 
  28.         //to authenticate the token in PUT methods  -https://forum.phalconphp.com/discussion/6422/sending-put-request-with-content-type-other-than-texthtml-fails
  29.         //this bug is due to the call to verifyResourceRequest in  bshaefer's oauth package.
  30.         if ($request->getMethod() == 'PUT')
  31.             $content $request->getContent();
  32.         if ($request->cookies->has('access_token')) {//if access token is set use it to set the HTTP_AUTHORIZATION
  33.             $_SERVER['HTTP_AUTHORIZATION'] = 'Bearer ' $request->cookies->get('access_token');
  34.         }
  35.         if (!$this->oauthService->verifyResourceRequest(\OAuth2\Request::createFromGlobals())) {
  36.             //$app['server']->getResponse()->send(); //send 401 response - Unauthorized;
  37.             $response = new CSProResponse();
  38.             $response->setError(401'Unauthorized''Unauthorized ');
  39.             $response->headers->set('Content-Length'strlen($response->getContent()));
  40.             return $response;
  41.         }
  42.         return null;
  43.     }
  44.     public function onKernelController(ControllerEvent $event) {
  45.         $controller $event->getController();
  46.         /*
  47.          * $controller passed can be either a class or a Closure.
  48.          * This is not usual in Symfony but it may happen.
  49.          * If it is a class, it comes in array format
  50.          */
  51.         if (!is_array($controller)) {
  52.             return;
  53.         }
  54.         //Except login controller all other UI controllers should be derived from TokenAuthenticatedController
  55.         //login controller once gets authenticated sets access_token cookie that is passed into the 
  56.         //requests from other controllers. Validate before sending a response for the UI as all UI
  57.         //requests now may not be requesting from the api endpoints (example RolesController)
  58.         if ($controller[0] instanceof TokenAuthenticatedController) {
  59.             if (!$event->getRequest()->cookies->has('access_token')) {
  60.                 $this->logger->debug("Missing token in the request. Redirecting to login screen.");
  61.                 $event->setController(function() {
  62.                     $url $this->router->generate('logout');
  63.                     $this->logger->debug("Redirecting to url $url");
  64.                     return new RedirectResponse($url);
  65.                 });
  66.             } else {
  67.                 $request $event->getRequest();
  68.                 $response $this->verifyResourceRequest($request);
  69.                 if ($response !== null) {
  70.                     $event->setController(function()use($response) {
  71.                         $this->logger->info("Unauthorized: Redirecting response to login page");
  72.                         $url $this->router->generate('logout');
  73.                         $this->logger->debug("Redirecting to url $url");
  74.                         return new RedirectResponse($url);
  75.                     });
  76.                 } else {
  77.                     //set the token storage. 
  78.                     $apiKey $request->cookies->get('access_token');
  79.                     $this->logger->debug("dashboard: setting token storage" $apiKey);
  80.                     $user $this->apikeyUserProvider->loadUserByApiKey($apiKey);
  81.                   //  $this->logger->debug("dashboard: setting token storage" . print_r($user, true));
  82.                     $roles $user->getRoles();
  83.                     $providerKey 'cspro_oauth_provider';
  84.                     /*$tokenStorage = new PreAuthenticatedToken(
  85.                             $user, $apiKey, $providerKey, $roles
  86.                     );*/  //deprecation https://github.com/symfony/symfony/issues/44396
  87.                     $tokenStorage = new PreAuthenticatedToken(
  88.                             $user$providerKey$roles
  89.                      );
  90.                     //set tokenstorage for authorization
  91.                    $this->tokenStorage->setToken($tokenStorage);
  92.                 }
  93.             }
  94.         }
  95.     }
  96.     public static function getSubscribedEvents() {
  97.         return [KernelEvents::CONTROLLER => 'onKernelController'];
  98.     }
  99. }