We have noticed when caching pages for anonymous users is active that on occasion a user is logged into our Drupal instance as the wrong user after CoSign authentication. The $_SERVER['remote_user'] variable is set to the correct user, however they are logged into Drupal as a previous user.

I haven't got a chance to do a lot of testing(on a tight deadline...), but I see you folks are checking to see if the remote user id is the same as the Drupal user id on line 89 of cosign.module:

if (!empty($remote->uid) && $user->uid == $remote->uid) 

and then calling the cosign_drupal_logout() function... except I don't believe it is ever getting called, as I do not see anything in my Drupal logs for it.

I have added watchdog logs for both the remote user, local drupal user, and if the logout function is called.

Infrastructure notes:

  • Apache/2.2.15 (Unix)
  • Cosign-3.2.0 Apache Filter installed from source
  • Memcached 1.4.4-3. ~ Running on a separate server

Thanks! and this is my first time posting on drupal.org... sorry in advance if I messed up on formatting or anything along those lines!

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

joelhowa’s picture

Status: Active » Closed (fixed)

Memcache issue. Sorry!

miannaccone’s picture

Status: Closed (fixed) » Active

I'm having the exact same issue described by joelhowa except I'm not running memcache. I'm only using Drupal's built in 'cache pages for anonymous users' option. I have dozens of users on my site and they randomly get logged in as other users who have authenticated before them. Disabling 'cache pages for anonymous users' fixes the problem.

ramzypro’s picture

Having the same issue described here, no memcache. We have 10,000+ nodes and disabling page caching is not an option for us due to server load, is that really the only solution?

Steps to re-create:
Re-creating is difficult, but it often happens when there are more than one user logged in. This happens for all users, including the default and custom roles we've defined. The primary administrator, though, is never affected.

Symptoms:
Users visit any https URL and see other users' information until they leave the page they first landed on. When they return to that page, they still see that previous user's information. Sometimes administrator users will not see the administrator menu block at all no matter where they browse.

mlhess’s picture

Issue summary: View changes
Status: Active » Fixed

So it looks like the path /user was getting cached and showing that you were logged in as a user that was not yourself. I have just committed a change to prevent this from happening. While this is a security issue (information disclosure) since there is not a stable release of the 7.x module, it does not need an SA.

mlhess’s picture

Status: Fixed » Needs work

I am reopening this issue. My fix works assuming that /user is the path that cosign sees for login.
For example

 <Location /user>
   CosignProtected             On
   CosignAllowPublicAccess       Off
 </Location>
kevinchampion’s picture

Status: Needs work » Needs review
FileSize
2.64 KB

After spending some time exploring and debugging, the problem seems to be that non-anonymous page requests are being cached from time-to-time (when caching is turned on). This is likely happening in the reported instances when users are actually still logged in to the central cosign server, but they have just switched between https and http protocol on subsequent page requests (assuming local cosign is setup to force authentication over all https requests, as is common practice). As a result, when the logged-in user places a request to the http protocol, drupal does not recognize the user's session because the protocol has changed and thus drupal's bootstrap occurs in a state whereby bootstrap uses the anonymous user (and the $user object is thus empty when cosign module tries to use it in hook_menu_get_item_alter).

Since page cache does not occur if a user is authenticated, the fact that bootstrap sees an anonymous user tells it to go ahead and set the page cache for the page the user is loading. While the cache is set, the user does not perceive any abnormal behavior and the page still loads as it should. This is because later in drupal's order of operations (hook_menu_get_item_alter in this case), the user is found to be still logged in and cosign module logs the user in to drupal. However, the mere fact that the page was cached in the first place is a problem because it means when another user encounters the same scenario (whereby they're still logged in to cosign but drupal does not see them as logged in) they will receive the cached copy of the page from the user who was logged in when the cache was set, as retrieved from the cache_page table.

I suspect that there are more and less helpful server and local cosign configurations that enable this scenario to take place, and that the problem could likely be addressed solely by means of server configuration alone (although I couldn't tell you want that configuration would be).

Nevertheless, this indicates a problem with cosign module, namely that all or part of the core functionality that logs users in and keeps them logged in may need to happen earlier in bootstrap (hook_boot) to prevent these pages from being cached in the first place. That being said, it's not best practice to force a lot of behavior into hook_boot because drupal bootstrap is a highly interdependent series of processes and steps and leapfrogging, skipping, or accelerating them can lead to detrimental side-effects.

Due to all this, we can try to refocus on the immediate problem, that drupal caching is caching pages it shouldn't be. This focus allows us to add a minimal check in hook_boot to see if local cosign has stored a remote user in the $_SERVER variable, and if so, turn off caching for the page request. The idea here is to use hook_boot to speculate about the forthcoming authentication inspection in hook_menu_get_item_alter and prevent the page caching from happening before it gets to that point (page caching occurs in hook_exit).

/**
 * Implements hook_boot().
 */
function cosign_boot() {

  global $conf;

  // We only want to run this code if hook_boot is called from
  // _drupal_bootstrap_page_cache() and not _drupal_bootstrap_page_header().
  if (!isset($_COOKIE[session_name()])) {

    $cosign_name = cosign_retrieve_remote_user();

    if (!empty($cosign_name)) {

      // Disable caching for this page request.
      $conf['cache'] = FALSE;
      // Then resume the bootstrap phase.
      drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

    }

  }

}

The following were helpful examples of other approaches to similar problems:

Please help test this by installing the latest development HEAD in your cosign authenticated Drupal 7 sites and report back if you're able to reproduce the same problems.

http://drupalcode.org/project/cosign.git/commit/7f8e61c7a917790db79edd0e...

kbk’s picture

Commit @#6 appears to resolve the issue for me.

kevinchampion’s picture

If one or two more can test and confirm this approach works in their environments, feel free to mark as "Reviewed & tested by the community" and then we can go ahead and create a new tagged release.

ramzypro’s picture

Based on observations, commit #6 resolves the issue here as well. See below.

mlhess’s picture

Status: Needs review » Fixed

Marking fixed

ramzypro’s picture

See below.

ramzypro’s picture

Status: Fixed » Active

I retract my statement; I am still finding https://[our domain] records in {cache_page} that are serving the wrong information to visitors that use cosign to veiw our site, even with the patch in #6 in place.

ramzypro’s picture

FileSize
51.92 KB

Is anyone maintaining this module? I am still dealing with reports of users seeing incorrect information when they log in; and I'm still seeing https://[our domain] records in {cache_page} that prove the issue isn't fixed with the above patch in place. This is an urgent problem and it is critical that it be fixed.Cached https URLs in database

EDIT: We're currently solving the problem by regularly running the sql query:

delete from {cache_page} where cid like 'https%'

This is not a solution that we are satisfied with.

mlhess’s picture

Status: Active » Postponed (maintainer needs more info)

This seems to be a side effect of ITS hosting. I have not been able to replicate this anywhere else. Please feel free to use my contact form to get more information. (or just email me at my umich address)

Michael

ramzypro’s picture

After reviewing the code logic, we removed the line

if (!isset($_COOKIE[session_name()])) {

and the corresponding closing brace from kevinchampion's patch, and there have been no occurrences in the week since. We'll continue to monitor the situation but I propose this be tested as a solution.

  • Commit 9eeb742 on 7.x-1.x by kevinchampion:
    Issue #2059581 by ramzypro: Remove unncessary cookie check.
    
    Removes...
kevinchampion’s picture

Status: Postponed (maintainer needs more info) » Needs review

I've had a chance to review #15 and I think I'm okay with it. I'm a little bit concerned that this may create a situation where it's too aggressive and pages are prevented from being cached when they should be, but I'm not certain this is a real concern. The problem though, is that if it is doing this it'll have a performance impact but without digging in and really watching for it, you may not be aware.

I've gone ahead and made the requested change. You can check it out on the latest dev HEAD.

ramzypro’s picture

Our issue has not resurfaced since removing that line; I believe it is fixed.

We have been monitoring performance since implementing this repair and have noticed no difference for anonymous users.

Drupal's default cache implementation is "cache pages for anonymous users" and since the "no cache" will only trigger when a user is within cosign, they are authenticated and shouldn't be receiving cached pages anyway. We have recently implemented the default block caching option and it is unaffected by this change as well.

I'm not sure how removing that line will impact third-party caching modules, but it shouldn't impact the default Drupal caching. I feel it would be helpful to implement these changes into the next beta release for further testing.

ramzypro’s picture

After four months plus of testing, I see no reason not to move this fix into a beta so that others may benefit.

myersca’s picture

We also had this problem on our new install using 7.x-1.0-beta3 and moving to the dev version fixed it for us. This was a pretty big issue as users were afraid there was a security problem when they logged in and saw someone else's account show up. While our site really has nothing super secure, it made people lose confidence in the site. We have been running the dev version for about 4 weeks now and no complaints considering we had complaints day one with the accounts showing up with the old module.

kevinchampion’s picture

Status: Needs review » Reviewed & tested by the community
kevinchampion’s picture

Version: 7.x-1.x-dev » 7.x-1.0-beta4
Status: Reviewed & tested by the community » Closed (fixed)