I have a D8.6.1 site with Masquerade enabled. I recently upgraded to 8.6.1 and the masquerade functionality started failing. Here's what happens:

1. I am logged in as admin, go to People and choose "Masquerade as" for a user (have tried several, admin and non-admin)
2a. If the user I'm masq'ing is an admin, I am redirected to the same People screen I was on, receive an "Access denied" message, and appear to be completely logged out.
2b. If the user I'm masq'ing is a non-admin, I am redirected to the front page and I am completely logged out.
3. When I try to log in again as the admin user, I am redirected to "user/1" and receive an Access Denied message and remain logged out
4. If I try once more to log in as the admin user, it succeeds and I am redirected to "user/1" which loads successfully.

It seems that the attempt to masq is causing some sort of authentication confusion that lasts through the next login attempt at which point it is somehow reset and works normally.

Issue fork masquerade-3019665

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

jptillman created an issue. See original summary.

trickfun’s picture

I have the same problem.
when i try to masquerade i get Access Denied message and remain logged out

drupal 8.6.4 and masquerade 2 beta-2

thanks in advance

tstermitz’s picture

Priority: Normal » Critical

I can confirm the same behavior.

As this makes masquerade non-functional, I'm marking it as critical.

gandel’s picture

Thank you for this great module but it didn't work.
Anytime I'm masq'ing, it's logged me out.
I have a drupal 7.67 installed

denisev’s picture

Might be a different reason for the others here, but in our install it was the case when the user had not yet confirmed Terms & Conditions by the Legal module.

brussam’s picture

I have the same problem as the initial issue.
I am running Drupal 9.0.2 and Masquerade 2.0@beta
Related logs entries
Path: /history/1052/read. Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: in Drupal\history\Controller\HistoryController->readNode() (line 48 of /home/ftpuser/RetamaD9/web/core/modules/history/src/Controller/HistoryController.php).

Path: /history/1051/read. Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: in Drupal\history\Controller\HistoryController->readNode() (line 48 of /home/ftpuser/RetamaD9/web/core/modules/history/src/Controller/HistoryController.php).

Path: /quickedit/attachments?_wrapper_format=drupal_ajax. Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: The 'access in-place editing' permission is required. in Drupal\Core\Routing\AccessAwareRouter->checkAccess() (line 120 of /home/ftpuser/RetamaD9/web/core/lib/Drupal/Core/Routing/AccessAwareRouter.php).

All errors say
Anonymous (not verified)

rasikap’s picture

I tried replicating issue as mentioned in comment#6, but couldn't replicate.

I was able to masquerade and navigate as both admin and non admin users.

Thanks!

brussam’s picture

rasikap, were you on Drupal 9? Lots of things have ceased to work on Drupal 9 that were fine on Drupal 8.

tim corkerton’s picture

This situation occurs for me too (as per https://www.drupal.org/project/masquerade/issues/3019665#comment-13622945) when I have the Legal module installed on latest Drupal 8 and when users have not accepted the Legal T&C's

brussam’s picture

In my circumstance, Drupal 9.0.2, there is no Legal Module for Drupal 9 and has never been used.

As a diagnostic, I just did a clean new install of Drupal 9.0.2 and a Composer required drupal/masquerade ^2.0@beta install. Added a user and masquerade worked. So something must be stepping on the masquerade module. Time for a binary search of which module is doing it.

Didn't take long to find drupal/redirect_after_login:^2.6 causes drupal/masquerade to crash. Now it is time for someone with coding skills to fix this.

My solution was to use a patched version of login_direction:2.0.0-alpha1 instead of redirect_after_login.

sgroundwater’s picture

I had hit a few minor snags with Masquerade 8.x-2.0-beta4 on Drupal 9.3.7. In the end, the issues were on my side.
Here are a few things to watch out for:
1.) Make sure the user is not set as "blocked". This will do strange things, with no clear info in the activity log. Basically you will redirect to the frontpage, where you'll see both a login and unmasquerade option. Clicking the unmasquerade link will show that the Anonymous account logged out.
2.) If you use a special login module like SimpleSAML / Shibboleth, ensure that the user account can log in locally.

jnicola’s picture

Tried to update to latest RC1 release to see if it fixed this issue. It did not and I still have it.

I'm not sure this needs to be considered critical though. It's more annoying than anything as it can be worked around.

frob’s picture

I think this is more of a Legal module issue. Here is a link to the issue in the legal module https://www.drupal.org/project/legal/issues/2638224

Raveen Thakur made their first commit to this issue’s fork.

solideogloria’s picture

This can't be a bug with Masquerade on its own, as it's working fine.

introfini’s picture

I encountered and solved this exact issue. The root cause is stale CSRF tokens being cached after session regeneration during the masquerade process.

Root Cause:

The masquerade process calls $this->sessionManager->regenerate() in Masquerade::switchUser() which invalidates the CSRF token seed stored in session metadata. When masquerade URLs are cached (which happens with lazy builders and entity operations), the cached CSRF tokens become invalid after the first masquerade attempt.

Solution:

I created a custom route processor to ensure fresh CSRF tokens are always generated for masquerade routes. This single solution fixes the issue completely:

1. Create a custom route processor

src/Routing/MasqueradeRouteProcessor.php:


namespace Drupal\[YOUR_MODULE]\Routing;

use Drupal\Core\Access\CsrfTokenGenerator;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface;
use Symfony\Component\Routing\Route;

/**
 * Processes outbound routes for masquerade to ensure fresh CSRF tokens.
 * 
 * Issue: Masquerade fails with 403 Access Denied on second attempt due to
 * stale CSRF tokens being cached. The masquerade process regenerates the
 * session ID which invalidates previously cached CSRF tokens.
 */
class MasqueradeRouteProcessor implements OutboundRouteProcessorInterface {

  protected $csrfTokenGenerator;

  public function __construct(CsrfTokenGenerator $csrf_token_generator) {
    $this->csrfTokenGenerator = $csrf_token_generator;
  }

  public function processOutbound($route_name, Route $route, array &$parameters, BubbleableMetadata $bubbleable_metadata = NULL) {
    // Only process masquerade routes
    if ($route_name === 'entity.user.masquerade') {
      // Force uncacheable to prevent stale CSRF tokens
      if ($bubbleable_metadata) {
        $bubbleable_metadata->setCacheMaxAge(0);
        $bubbleable_metadata->addCacheContexts(['session']);
      }
      
      // Generate a fresh CSRF token for this specific route
      $path = ltrim($route->getPath(), '/');
      foreach ($parameters as $param => $value) {
        $path = str_replace("{{$param}}", $value, $path);
      }
      
      // Add fresh token to parameters
      if (!isset($parameters['token'])) {
        $parameters['token'] = $this->csrfTokenGenerator->get($path);
      }
    }
  }
}

2. Register the service

In your module's services.yml:

services:
your_module.masquerade_route_processor:
class: Drupal\your_module\Routing\MasqueradeRouteProcessor
arguments: [ '@csrf_token' ]
tags:
- { name: route_processor_outbound, priority: 1000 }

Result:

This solution ensures that:

  • Fresh CSRF tokens are generated for every masquerade request
  • Masquerade URLs are never cached to prevent stale token reuse
  • The fix works consistently across multiple masquerade attempts

Masquerade now works reliably on subsequent attempts without the 403 Access Denied error.

This fix addresses the core issue without requiring changes to the masquerade module itself, making it a safe workaround until the module is updated to handle this scenario properly.