How to redirect an anonymous user to the login form after a 403 error? I want to redirect an anonymous user to the login form if such user encounters a 403 error.

I have created event subscriber and this is my code, but I end up on loop on the current page.

/**
   * Redirect anonymous user to login page if he encounters 404 or 403
   * response.
   *
   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $response
   *   The created response object that will be returned.
   * @param string $event
   *   The string representation of the event.
   * @param \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher $event_dispatcher
   *   Event dispatcher that lazily loads listeners and subscribers from the dependency injection
   *   container.
   */
  public function checkLoginNeeded(GetResponseEvent $response, $event, ContainerAwareEventDispatcher $event_dispatcher) {
    $routeMatch = RouteMatch::createFromRequest($response-&gt;getRequest());
    $route_name = $routeMatch-&gt;getRouteName();
    $is_anonymous = \Drupal::currentUser()-&gt;isAnonymous();
    $is_not_login = $route_name != 'user.login';

    if ($is_anonymous &amp;&amp; $route_name == 'system.403' &amp;&amp; $is_not_login) {
      $query = $response-&gt;getRequest()-&gt;query-&gt;all();
//      $query['destination'] = $routeMatch-&gt;getRouteObject()-&gt;getPath();
      $query['destination'] = \Drupal::url('&lt;current&gt;');
      $login_uri = \Drupal::url('user.login', [], ['query' =&gt; $query]);
      $returnResponse = new RedirectResponse($login_uri, Response::HTTP_FOUND);
      $response-&gt;setResponse($returnResponse);
    }
  }




I think this is related to the fact that the response already contains destination(current uri) and system.404 and system.403 have some high priority that prevent me to override this.
I've seen that this question was never answered how to do this programmatically. The code actually does work, when placed in an Exception Subscriber:

/src/EventSubscriber/RedirectOn403Subscriber.php:

&lt;?php

namespace Drupal\mymodule\EventSubscriber;

use Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;

class RedirectOn403Subscriber extends HttpExceptionSubscriberBase {

  protected $currentUser;

  public function __construct(AccountInterface $current_user) {
    $this-&gt;currentUser = $current_user;
  }

  protected function getHandledFormats() {
    return ['html'];
  }

  public function on403(GetResponseForExceptionEvent $event) {
    $request = $event-&gt;getRequest();
    $is_anonymous = $this-&gt;currentUser-&gt;isAnonymous();
    $route_name = $request-&gt;attributes-&gt;get('_route');
    $is_not_login = $route_name != 'user.login';
    if ($is_anonymous &amp;&amp; $is_not_login) {
      $query = $request-&gt;query-&gt;all();
      $query['destination'] = Url::fromRoute('&lt;current&gt;')-&gt;toString();
      $login_uri = Url::fromRoute('user.login', [], ['query' =&gt; $query])-&gt;toString();
      $returnResponse = new RedirectResponse($login_uri);
      $event-&gt;setResponse($returnResponse);
    }
  }

}


mymodule.services.yml:

services:
  mymodule.exception403.subscriber:
    class: Drupal\mymodule\EventSubscriber\RedirectOn403Subscriber
    tags:
      - { name: event_subscriber }
    arguments: ['@current_user']