Prevent ‘access of authenticated pages’ after user logout on pressing browser back.

Deepak Tomar
2 min readNov 29, 2023

--

Problem Statement:

In one of our Drupal projects we were facing an issue that user was able to access authenticated pages even after logout on hitting browser back button.

These pages were getting served by cache and browser history. Even though the content is in read-only state and user cannot perform any operation like add/delete/update but still it is possible to steal admin information without proper access.

Problem solution:

To prevent this issue we need to set proper cache headers like “no-store” in our website for logged-in/authenticated user.

What is ‘no-store’ header?

The no-store directive means browsers aren’t allowed to cache a response and must pull it from the server each time it’s requested.

There are other headers also available in order to achieve specific cache functionality like: “no-cache, max-age=0, must-revalidate, post-check=0, pre-check=0”

To set the required headers we created a custom EventSubscriber.

src/EventSubscriber/CommonSubscriber.php contains a class that implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
Below is the code to set the header:

<?php

namespace Drupal\common_module\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Drupal\Core\Session\AccountInterface;

/**
* Common module event subscriber.
*/
class CommonSubscriber implements EventSubscriberInterface {

/**
* Current user object.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;

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

/**
* Kernel response event handler.
*
* @param \Symfony\Component\HttpKernel\Event\ResponseEvent $event
* Response event.
*/
public function onKernelResponse(ResponseEvent $event) {
// The event occurs once a response was created for replying to a request.
// For example you could override or add extra HTTP headers in here.
$response = $event->getResponse();
$loggedInuser = $this->currentUser->isAuthenticated();
// If user is login, add Cache-Controll as no-store.
if ($loggedInuser == TRUE) {
$cacheControl = 'no-store,' . $event->getRequest()->headers->get('Cache-Control');
$response->headers->set('Cache-Control', $cacheControl);
}
}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
KernelEvents::RESPONSE => ['onKernelResponse'],
];
}

}

Flush cache after implementing this code.

Now user will get ‘access denied’ on visiting the admin pages after logout using history or browser back button.

--

--