18

I want if user not logged in and visit any page of my website except my REST VIEWS routers I redirect him/her to login page in drupal 8, I found this solutions for drupal 7 but didn't find any solution for Drupal 8,

4
  • 2
    In code you would write an event subscriber to act on KernelEvents::REQUEST event and then set the response to a RedirectResponse for the login page.
    – mradcliffe
    Dec 15, 2016 at 21:47
  • 1
    I thought of something else. You could set the 403 page to /user and then if they're anonymous, it would take them to /user/login, but with the side effect of taking authenticated users to their user profile without telling them they've been denied access to the page they were looking for.
    – mradcliffe
    Dec 15, 2016 at 22:54
  • 1
    Use the following module to add a login redirect for anonymous users, it has a setting to exclude paths so I think you can add your rest paths in that. drupal.org/project/anonymous_redirect Mar 22, 2018 at 10:49
  • 1
    This module also does the job: drupal.org/project/anonymous_login Jul 17, 2019 at 14:22

4 Answers 4

24

You can test a user's status very early with event subscriber in a custom module that subscribes to KernelEvents::REQUEST.

First, you register the event subscriber in mymodule.services.yml in your module folder:

services:
  mymodule.event_subscriber:
    class: Drupal\mymodule\EventSubscriber\RedirectAnonymousSubscriber
    arguments: []
    tags:
      - {name: event_subscriber}

Then add RedirectAnonymousSubscriber.php for your custom event subscriber in your module in the /src/EventSubscriber/ folder.

namespace Drupal\mymodule\EventSubscriber;

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

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

  public function __construct() {
    $this->account = \Drupal::currentUser();
  }

  public function checkAuthStatus(GetResponseEvent $event) {

    if ($this->account->isAnonymous() && \Drupal::routeMatch()->getRouteName() != 'user.login') {

      // 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('/user/login', 301);
      $event->setResponse($response);
      $event->stopPropagation();
    }
  }

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

}
7
  • thanks to @mradcliffe for the idea for the event subscriber
    – oknate
    Dec 15, 2016 at 23:03
  • 1
    he should create RedirectAnonymousSubscriber.php ,I update your answer.
    – Yuseferi
    Dec 16, 2016 at 8:28
  • @oknate what if user is on /registration or /forget-password or /logout route ? Shouldn't it check for those routes as well in the if condition ? As as per this, the user might be redirect while registering or request for the new password.
    – Juyal Jee
    Jul 17, 2019 at 6:48
  • 2
    Another important detail here is "priority" of the subscriber. I found some routes will resolve before the redirect above kicks in. But setting the priority (a higher number fires first) helps to resolve that. In the example above, use array('checkAuthStatus', 100). Docs on subscriber and priority: symfony.com/doc/current/event_dispatcher.html
    – BWagner
    Feb 7, 2020 at 1:39
  • 1
    Thanks oknate for this snippet. I've had to tweak it a bit to also allow other user paths like password reset etc. stefvanlooveren.me/blog/… Feb 10, 2021 at 10:30
9

First, create a service for your event subscriber in module-name.services.yml

Code -

services:
    [MODULE-NAME]_event_subscriber:
        class: Drupal\MODULE-NAME\EventSubscriber\[Event-Subscriber-class]
        tags:
        - {name: event_subscriber}

Create your own eventsubscriber class inside modules/module-name/src/EventSubscriber directory:

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

class Event-Subscriber-class implements EventSubscriberInterface {

  private $redirectCode = 301;

  public function checkForRedirection2(GetResponseEvent $event) {
    $account = \Drupal::currentUser(); 
    if (empty($account->id()) {
      $response = new RedirectResponse('/', $this->redirectCode);
      $response->send();
      exit(0);
    }
  }

  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = array('checkForRedirection2');
    return $events;
  }
}
8

On Drupal 8.3.3, this code causes an endless redirection. I've fixed that by adding that instead.

..
$response = new RedirectResponse('/user/login', 301);
$response->send();
..
0
2

This answer is compatible for Drupal 8, and 9.

First, you register the event subscriber in redirect_anonymous_users.services.yml in your module folder (taken from @oknate's answer):

services:
  redirect_anonymous_users.event_subscriber:
    class: Drupal\redirect_anonymous_users\EventSubscriber\RedirectAnonymousSubscriber
    arguments: []
    tags:
      - {name: event_subscriber}

Then add RedirectAnonymousSubscriber.php for your custom event subscriber in your module in the /src/EventSubscriber/ folder.

namespace Drupal\redirect_anonymous_users\EventSubscriber;

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

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

  public function checkAuthStatus(GetResponseEvent $event) {
    if (
      \Drupal::currentUser()->isAnonymous() &&
      \Drupal::routeMatch()->getRouteName() != 'user.login'
    ) {
      $response = new RedirectResponse('/user/login', 302);
      $response->send();
    }
  }

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

    return $events;
  }

}
1
  • Nice example! But it wold be better if it used Dependency Injection instead of hard-wired calls to \Drupal::currentUser() and \Drupal::routeMatch().
    – berliner
    Oct 28, 2021 at 20:57

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.