elb98rm
elb98rm

Reputation: 800

How to redirect from a EventSubscriber in Symfony 5

I'm attempting to write a custom auth checker for Symfony5. This is to run on selected Controllers, all of which have an AuthenticationControllerInterface which includes numerous other bits of relevant code.

I am attempting to use an EventSubscriber bound to the ControllerEvent. This checks for this interface and identifies correctly the relevant controllers.

Please see the below for context:


class BearerTokenSubscriber implements EventSubscriberInterface
{

    public function onKernelController(ControllerEvent $event)
    {
            $controller = $event->getController();

            // load the controller
            if (is_array($controller)) {
                $controller = $controller[0];
                if ($controller instanceof AuthenticationControllerInterface) {
                    if(
                       // my assorted auth functionality: works as expected
                    ) {
                        //... where my question lies:
                    }
                }
            }
        }
    }

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::CONTROLLER => 'onKernelController',
        ];
    }
}

At "where my question lies": is the point I want to do a redirect... in the following ways (in order of preference):

  1. returning a specific controller method (I have a 403 pre-configured).
  2. redirecting to another URL (with a 403)

Thanks in advance.

Upvotes: 0

Views: 985

Answers (2)

elb98rm
elb98rm

Reputation: 800

The specific answer in my case was:


if (/* some test logic */) {
    $event->stopPropagation();
    $event->setController(
        static function () use ($controller) {
            return $controller->some403ErrorResponse();
        }
    );
}

Many thanks to Jeroen who pointed me in the correct direction. Have marked his as correct also.

Upvotes: 0

Jeroen van der Laan
Jeroen van der Laan

Reputation: 724

You can use ControllerEvent::setController($myController) to provide a controller of your choice once your conditions are met:

class TestControllerEventSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        $events = [];
        $events[KernelEvents::CONTROLLER] = ['onKernelController', 0];
        return $events;
    }

    public function onKernelController(ControllerEvent $event): void
    {
        $controller = $this->getControllerObjectFromEvent($event);
        // Check if your conditions are met
        if ($controller instanceof AuthenticationControllerInterface && $whateverElse) {
            $event->stopPropagation();
            // Set your custom controller that produces a 403 response
            $event->setController(static function () {
                return new Response(null, 403);
            });
        }
    }

    private function getControllerObjectFromEvent(ControllerEvent $event): ?object
    {
        $controller = $event->getController();
        if (true === is_object($controller)) {
            return (object) $controller;
        }
        if (false === is_array($controller)) {
            return null;
        }
        foreach ($controller as $value) {
            if (true === is_object($value)) {
                return $value;
            }
        }
        return null;
    }
}

Upvotes: 1

Related Questions