2

I have injected currentUser as a dependency into my HTTP middleware, but when I check the UID while logged in, the result is always 0.

I am logged in as an admin and refreshing the watchdog page; the log messages show the UID is always 0. $this->currentUser->isAnonymous() also returns 1, so my code is running at the wrong time. However, I don't know how to adjust the priority to ensure the HTTP middleware runs at a time when I have access to the uid.

(Goal: I am trying to send site analytics server-side, so I want access to the UID and current path-- I've omitted injecting the current path in the example below, but to get the current path, the middleware must have a priority of less than 100.)

class Analytics implements HttpKernelInterface {

  /**
   * Current request.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected RequestStack $requestStack;

  /**
   * The wrapped HTTP kernel.
   *
   * @var \Symfony\Component\HttpKernel\HttpKernelInterface
   */
  protected HttpKernelInterface $httpKernel;

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

  /**
   * Logger factory.
   *
   * @var \Drupal\Core\Logger\LoggerChannelInterface
   */
  protected LoggerChannelInterface $loggerFactory;

  /**
   * Creates a HTTP middleware handler.
   *
   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $kernel
   *   The HTTP kernel.
   */
  public function __construct(HttpKernelInterface $kernel, RequestStack $request_stack, AccountInterface $current_user, LoggerChannelFactoryInterface $logger_factory) {
    $this->httpKernel = $kernel;
    $this->requestStack = $request_stack;
    $this->currentUser = $current_user;
    $this->loggerFactory = $logger_factory->get('analytics');
  }

  /**
   * {@inheritdoc}
   */
  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE): Response {
    if ($type === self::MASTER_REQUEST) {
      $user_id = $this->currentUser->id();
      $this->loggerFactory->info("Found UID: $user_id");
    }
    return $this->httpKernel->handle($request, $type, $catch);
  }

}

MYMODULE.services.yml

  MYMODULE.analytics_middleware:
    class: Drupal\mymodule\Middleware\Analytics
    # Skip the first argument because it is injected by Drupal.
    arguments: ['@request_stack', '@current_user', '@logger.factory' ]
    tags:
      - { name: http_middleware, priority: 1000 }

For the priority, I tried 1000, 100, 0, -100, and -1000, all of which give the same result (UID = 0).

1
  • 3
    User authentication does not happen in a middleware, it's in the request event subscriber AuthenticationSubscriber with priority 300. So you would need to return the response from a request event subscriber with priority <300.
    – 4uk4
    Aug 19 at 7:09

1 Answer 1

3

User authentication does not happen in a middleware, it's in the request event subscriber AuthenticationSubscriber with priority 300:

  public static function getSubscribedEvents() {
    // The priority for authentication must be higher than the highest event
    // subscriber accessing the current user. Especially it must be higher than
    // LanguageRequestSubscriber as LanguageManager accesses the current user if
    // the language module is enabled.
    $events[KernelEvents::REQUEST][] = ['onKernelRequestAuthenticate', 300];

    ...

    return $events;
  }

So you would need to set the response in your own request event subscriber with priority <300, if you don't want to wait until the Drupal kernel has finished all request event subscribers and hands over control to the controller you have defined in a route which matches the requested path.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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