You are here

protected function SamlController::handleExceptionInRenderContext in SAML Authentication 4.x

Same name and namespace in other branches
  1. 8.3 src/Controller/SamlController.php \Drupal\samlauth\Controller\SamlController::handleExceptionInRenderContext()

@todo in 4.x, always throw; move our own error handling into AccessDeniedSubscriber. This means the situation of error_throw=TRUE will become standard. It would be nice to first do some investigation if contrib modules doing error redirection (customerror / error_redirect?) are mature / have good code, before doing this. If so, we can safely get rid of the 'error_redirect_url' setting and recommend installing a module if this functionality is needed.

Overrides ExecuteInRenderContextTrait::handleExceptionInRenderContext

File

src/Controller/SamlController.php, line 468

Class

SamlController
Returns responses for samlauth module routes.

Namespace

Drupal\samlauth\Controller

Code

protected function handleExceptionInRenderContext(\Exception $exception, $default_redirect_route, $while = '') {
  if ($exception instanceof TooManyRequestsHttpException) {

    // If this ever happens, don't spend time on a RedirectResponse (when the
    // redirected page will need to spend time rendering the page that
    // includes an error message. Throwing an exception here will fall
    // through to the Symfony HttpKernel - and unfortunately for us, Drupal's
    // CustomPageExceptionHtmlSubscriber will intercept the response handling
    // and redirect anyway, unless we intercept it first in our own
    // AccessDeniedSubscriber.)
    throw $exception;
  }
  $config = $this
    ->config(self::CONFIG_OBJECT_NAME);

  // This config value (possibly together with 'error_redirect_url') will
  // likely be removed in the 4.x version of the module - and we'll always
  // throw an exception for errors. (This module's default error handling
  // will then be in an event subscriber which can more easily be
  // overridden. For now, explicitly set 'error_throw' if you want to
  // have your own event subscriber catch handle the error on a
  // KernelEvents::EXCEPTION event - see AccessDeniedSubscriber for example.)
  if ($config
    ->get('error_throw')) {
    throw new AccessDeniedHttpException($exception
      ->getMessage(), $exception);
  }
  if ($exception instanceof UserVisibleException || $config
    ->get('debug_display_error_details')) {

    // Show the full error on screen; also log, but with lowered severity.
    // Assume we don't need the "while" part for a user visible error because
    // it's likely not fully correct.
    $this->messenger
      ->addError($exception
      ->getMessage());
    $this->logger
      ->warning($exception
      ->getMessage());
  }
  else {

    // Use the same format for logging as Drupal's ExceptionLoggingSubscriber
    // except also specify where the error was encountered. (The options for
    // the "while" part are limited, so we make this part of the message
    // rather than a context parameter.)
    if ($while) {
      $while = " while {$while}";
    }
    $error = Error::decodeException($exception);
    unset($error['severity_level']);
    $this->logger
      ->critical("%type encountered{$while}: @message in %function (line %line of %file).", $error);

    // Don't expose the error to prevent information leakage; the user likely
    // can't do much with it anyway. But hint that more details are available.
    $this->messenger
      ->addError("Error encountered{$while}; details have been logged.");
  }

  // Get error URL.
  $url = $config
    ->get('error_redirect_url');
  $url_object = NULL;
  if ($url) {
    $url = $this->token
      ->replace($url);
    $url_object = $this->pathValidator
      ->getUrlIfValidWithoutAccessCheck($url);
    if (empty($url_object)) {
      $this
        ->getLogger('samlauth')
        ->warning("The Error Redirect URL is not a valid path; falling back to provided route @route.", [
        '@route' => $default_redirect_route,
      ]);
    }
  }
  if (empty($url_object)) {
    $url_object = Url::fromRoute($default_redirect_route);
  }
  return $url_object;
}