Skip to content

Instantly share code, notes, and snippets.

@jorislucius
Last active April 2, 2023 19:16
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jorislucius/8c524fb45e8a25657d474c0abe9ef48f to your computer and use it in GitHub Desktop.
Save jorislucius/8c524fb45e8a25657d474c0abe9ef48f to your computer and use it in GitHub Desktop.
Drupal 8 | Redirect all anonymous users to login page. With a few needed exceptions like /user/password
<?php
namespace Drupal\<yourmodulename>\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Event subscriber subscribing to KernelEvents::REQUEST.
*/
class RedirectAnonymousSubscriber implements EventSubscriberInterface {
public function checkAuthStatus(GetResponseEvent $event) {
global $base_url;
if (
\Drupal::currentUser()->isAnonymous() &&
\Drupal::routeMatch()->getRouteName() != 'user.login' &&
\Drupal::routeMatch()->getRouteName() != 'user.reset' &&
\Drupal::routeMatch()->getRouteName() != 'user.reset.form' &&
\Drupal::routeMatch()->getRouteName() != 'user.reset.login' &&
\Drupal::routeMatch()->getRouteName() != 'user.pass' ) {
// add logic to check other routes you want available to anonymous users,
// otherwise, redirect to login page.
$route_name = \Drupal::routeMatch()->getRouteName();
if (strpos($route_name, 'view') === 0 && strpos($route_name, 'rest_') !== FALSE) {
return;
}
$response = new RedirectResponse($base_url . '/user/login', 301);
$event->setResponse($response);
$event->stopPropagation();
return;
}
}
public static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = array('checkAuthStatus');
return $events;
}
}
@ashish-cummins
Copy link

hello,

This is really helpful understand Event Subscriber. I am also trying to redirect anonymous user to login page with your code. but it is not working for me, it is giving me "Redirecting too many times..." error. Can you please help why this is happening and what is the solution over it. Thanks in advance.

@ashish-cummins
Copy link

capture

@yommu
Copy link

yommu commented Sep 18, 2018

@ashish-cummins with latest version of Drupal, try to replace these lines:

$event->setResponse($response);
$event->stopPropagation();

with:

$response->send();

@gzveri
Copy link

gzveri commented Apr 4, 2019

this worked for me:

      $response = new RedirectResponse($base_url . '/user/login', 302);
//      $event->setResponse($response);
//      $event->stopPropagation();
//      return;
      $response->send();

@jorislucius
Copy link
Author

This module also does the job: https://www.drupal.org/project/anonymous_login

@saadwaseem
Copy link

This really helpful. Initially It went into error "redirecting too many times" but with @gzveri comment it got solved. Thanks.

@flyke
Copy link

flyke commented Oct 8, 2020

$response->send(); works for me too, thanks!

namespace Drupal\starterkit_helper\EventSubscriber;

use Drupal\Core\Url;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Event subscriber subscribing to KernelEvents::REQUEST.
 */
class RedirectAnonymousSubscriber implements EventSubscriberInterface {

  /**
   *
   */
  public function checkAuthStatus(GetResponseEvent $event) {

    $loginUrl = Url::fromRoute('user.login')->toString();
    $routeName = \Drupal::routeMatch()->getRouteName();

    if (
        \Drupal::currentUser()->isAnonymous() &&
        $routeName != 'user.login' &&
        $routeName != 'user.reset' &&
        $routeName != 'user.reset.form' &&
        $routeName != 'user.reset.login' &&
        $routeName != 'user.pass') {
      // Add logic to check other routes you want available to anonymous users,
      // otherwise, redirect to login page.
      if (strpos($routeName, 'view') === 0 && strpos($routeName, 'rest_') !== FALSE) {
        return;
      }

      $response = new RedirectResponse($loginUrl, 301);
      $response->send();
    }
  }

  /**
   *
   */
  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = ['checkAuthStatus'];
    return $events;
  }

}

@mogbril
Copy link

mogbril commented Feb 26, 2021

I've tried all the solutions and still got endless redirection

@rkhregar
Copy link

rkhregar commented Mar 4, 2021

@mogbril
i think you may have other redirection in your .htaccess or somewhere else that is creating loop

@lonalore
Copy link

lonalore commented Apr 2, 2023

My solution under Drupal v9.5.7:

<?php

namespace Drupal\[MODULE]\EventSubscriber;

use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Class EventSubscriber.
 */
class EventSubscriber implements EventSubscriberInterface {

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $account;

  /**
   * Constructor.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   The current user.
   */
  public function __construct(AccountInterface $account) {
    $this->account = $account;
  }

  /**
   * Redirects users when access is denied.
   *
   * @param \Symfony\Component\HttpKernel\Event\ExceptionEvent $event
   *   The event to process.
   */
  public function onException(ExceptionEvent $event) {
    $exception = $event->getThrowable();
    if ($exception instanceof HttpExceptionInterface && $exception->getStatusCode() === 403) {
      if (!$this->account->isAuthenticated()) {
        $url = Url::fromRoute('user.register');
        $response = new RedirectResponse($url->toString());
        $event->setResponse($response);
      }
    }
  }

  /**
   * Events.
   */
  public static function getSubscribedEvents(): array {
    return [
      KernelEvents::EXCEPTION                => [
        ['onException', 80],
      ],
    ];
  }

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment