2

I would like to remove unwanted effect of redirecting when somewhere is thrown AccesDeniedException. I mean redirecting to "login" page if user is not authenticated.

I created kernel.exception listener

class ApiAccessDeniedListener implements EventSubscriberInterface
{
    private $format;

    public function __construct($format = 'json')
    {
        $this->format = $format;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();
        // here some conditions
        if($exception instanceof AccessDeniedException){
            $exception = new AccessDeniedHttpException('You do not have the necessary permissions', $exception);
        }
    }

    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::EXCEPTION => array('onKernelException', 5),
        );
    }
}

This listener work properly in the correct order but all time firewall redirect me to login page. Symfony docs say that:

Exception Listener

If any of the listeners throws an AuthenticationException, the exception listener that was provided when adding secured areas to the firewall map will jump in.

The exception listener determines what happens next, based on the arguments it received when it was created. It may start the authentication procedure, perhaps ask the user to supply their credentials again (when they have only been authenticated based on a "remember-me" cookie), or transform the exception into an AccessDeniedHttpException, which will eventually result in an "HTTP/1.1 403: Access Denied" response.

I understand - If I throw AccessDeniedHttpException i should get instant 403 instead of redirecting, Am I correct?

Second - I dug symfony and ExceptionListener have the same trick? i think...

private function handleAccessDeniedException(GetResponseForExceptionEvent $event, AccessDeniedException $exception)
{
    $event->setException(new AccessDeniedHttpException($exception->getMessage(), $exception));
    //...
}

In addition symfony debugger show 2 exceptions after auth. (as it should):

Unable to access this page!
403 Forbidden - AccessDeniedHttpException
1 linked Exception: ... (and here AccessDeniedException)

First AccessDeniedException and second AccessDeniedHttpException.

How can i fix my problem? How can I throw instant 403 error?


EDIT

I found where is problem. Firewall ExceptionListener check all previous exceptions with loop:

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();
        do {
            if ($exception instanceof AuthenticationException) {
                return $this->handleAuthenticationException($event, $exception);
            } elseif ($exception instanceof AccessDeniedException) {
                return $this->handleAccessDeniedException($event, $exception);
            } elseif ($exception instanceof LogoutException) {
                return $this->handleLogoutException($exception);
            }
        } while (null !== $exception = $exception->getPrevious());
    }

I can change my listener to:

public function onKernelException(GetResponseForExceptionEvent $event)
{
    $exception = $event->getException();
    // here some conditions
    if($exception instanceof AccessDeniedException){
        //old version
        //$exception = new AccessDeniedHttpException('You do not have the necessary permissions', $exception);
        $exception = new AccessDeniedHttpException('You do not have the necessary permissions', $exception->getPrevious());
    }
}

New question is - Could it cause any security problems? I think this is good way.

Griva
  • 1,618
  • 20
  • 37

0 Answers0