Problem

If a user visits a page anonymously (and anonymous caching is enabled), they may receive a cached anonymous page with an associated ETag. If they then authenticate externally and return to the same page, drupal will validate the existing cached page (via ETag) during the bootstrap 'page_cache' phase (very early in the page lifecycle). The only hook that may be called during page cache validation is hook_boot() (and then only if 'page_cache_invoke_hooks' is enabled, which it is by default). The external validation has set the webserver authentication variables, but the current hook_boot() doesn't actually prevent the anonymous cached page from being verified by drupal (http status 302).

Solution

hook_boot() should detect caches when a cached page is being served to an externally authenticated user, and force the page to reload to force the web browser to retrieve a fresh copy of the page. However, sometimes drupal will force an authenticated user to logout (for example in maintenance mode when the user doesn't have a role with access). To prevent the reloads from looping, a very short lived tracking cookie (60 seconds?) can be used to check if a reload has been attempted for the specific user recently, and skip repeated reloads.

This is subtly different than Issue 2154059 in that an anonymous page is shown to an authenticated user, not the reverse. It does, however, also fix that issue in a simpler way (by never serving authenticated pages as cached).

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

sshambar’s picture

Attaching patch to force reload of cached pages when external authentication is detected.

Also disables caching of authenticated pages.

sshambar’s picture

To reproduce the bug in existing code:

  1. enable module (if not already)
  2. logout both externally and by clicking logout in drupal (to end drupal session)
  3. access a cached page as an anonymous or unrecognized user (eg homepage) - if you can view http headers, check that ETag has format the ########-# (with the dash) which indicates it's cached, repeated access should show as code 304 in the webserver logs
  4. login using external means (eg with a username that the module recognizes)
  5. revist page in step 2, only cached page is seen (still code 304) - clicking reload should show the correct authenticated page however...

To test the patch:

Repeat steps above... Last step should correctly show the authenticated page without a need to reload the page.

sshambar’s picture

Status: Active » Closed (fixed)

Merged into dev branch, thanks!