0

This is not a question about changing or preprocessing the twig template of the 403 page.

I have a controller with an access function called by the _custom_access key of my route.

In some circumstance, this function is returning AccessResult::forbidden("a good reason"); which lead to my default 403 page.

Most of the case, this is the behavior I would like to have, but in few cases, I would like to have another title and another message for this page like "You can not access because you eat too much chocolate"

Should I create a new custom error route and send a new response to this route from my access function? (hint: I tried without success)

Any idea?

Edit to add: Thanks to 4k4, I have added a custom ExceptionHtmlSubscriber extending DefaultExceptionHtmlSubscriber in order to override the on403() method.

Here is my code:

class TXSExceptionHtmlSubscriber extends DefaultExceptionHtmlSubscriber {
  /**
   * {@inheritdoc}
   */
  public function on403(ExceptionEvent $event) {
    $my_condition=extract_from_event($event);
    if($my_condition){
      // I am not sure it is what should be done here
      $this->makeSubrequest($event, '/my_custom_error_path/my_custom_error_code', Response::HTTP_FORBIDDEN);
    }else {
      parent::$this->on403($event);
    }
  }
  /**
   * {@inheritdoc}
   */
  protected static function getPriority() {
    return 1000;
  }
}

So far, I have 2 questions:

1-Unfortunately my custom on403() method is never called (on the other hand, the on403() method DefaultExceptionHtmlSubscriber is called): What I am missing?

2-Let say that my custom on403() method is called: what should be the code to redirect the user on my custom 403 page containing my custom message (ie: it could be nice to display the reason of the AccessResult AccessResult::forbidden("a good reason");

2
  • but in few cases – What cases exactly? What conditions?
    – leymannx
    Jan 24, 2021 at 21:18
  • For example role_A doesn't have access but needs a custom 403 message but role_B who haven't access too will be ok with the default 403 page.
    – Baud
    Jan 24, 2021 at 21:48

2 Answers 2

0

Access functions are only for calculating access results. You can't do anything else because this function is called multiple times, not only for incoming routes but also for outbound links.

To set a response use on403() of an ExceptionHtmlSubscriber. You can also set the result of a sub-request if you want a themed 403 message. See How can we catch the acces denied exception?

Edit: Answering further questions

1-Unfortunately my custom on403() method is never called (on the other hand, the on403() method DefaultExceptionHtmlSubscriber is called): What I am missing?

You need to register the service in mymodule.services.yml:

services:
  mymodule.exception_subscriber:
    class: Drupal\mymodule\EventSubscriber\MymoduleExceptionHtmlSubscriber
    tags:
      - { name: event_subscriber }

2-Let say that my custom on403() method is called: what should be the code to redirect the user on my custom 403 page containing my custom message (ie: it could be nice to display the reason of the AccessResult AccessResult::forbidden("a good reason");

You find the message in the exception object:

public function on403(ExceptionEvent $event) {
  // ...
  if ($my_condition) {
    $message = $event->getThrowable()->getMessage();
    $event->setResponse(new Response($message, 403));
  }
}

BTW you don't need to call parent::on403($event) because the parent registered with a lower priority will be called automatically when your event subscriber doesn't set a response.

1
  • Thank you. it looks like it is the solution, but I am stuck with 2 issues. Would you mind to read my updated question?
    – Baud
    Jan 25, 2021 at 14:25
0

If your eventsubscriber is not working yet, try updating the services yml file and adding the constructor to the class.

services:
  mymodule.exception_subscriber:
    class: Drupal\mymodule\EventSubscriber\MymoduleExceptionHtmlSubscriber
    tags:
      - { name: event_subscriber }
    arguments: ['@config.factory', '@http_kernel', '@logger.channel.php', '@redirect.destination', '@router.no_access_checks', '@access_manager']

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.