I'm seeing some odd behaviour on a site where some users (maybe due to browser settings?) are having their sessions expire / somehow become invalidated on browser close.

The side effect of this is that they:

  1. Open browser
  2. Open bookmark which deep links into the site
  3. Drupal detects that the session is expired / invalid (not sure exactly which)
  4. simplesamlphp_auth_user_logout() triggers
  5. The user is redirected back to either logout_goto_url in simplesamlphp_auth.settings OR base_path().

This is pretty confusing from the users perspective - they've opened a bookmark to page XYZ and instead have been confronted with page ABC.

simplesamlphp_auth.module:

function simplesamlphp_auth_user_logout($account) {
  $logout_url = \Drupal::config('simplesamlphp_auth.settings')->get('logout_goto_url');
  [...]
  if ($logout_url) {
    $simplesaml->logout($logout_url);
  }
  else {
    $simplesaml->logout();
  }
}

SimplesamlphpAuthManager:

  public function logout($redirect_path = NULL) {
    if (!$redirect_path) {
      $redirect_path = base_path();
    }
    $this->instance->logout($redirect_path);
  }
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

George Bills created an issue. See original summary.

George Bills’s picture

I thought the fix might be to remove the explicit setting of redirect_path in SimplesamlphpAuthManager::logout(), but it looks like that's required just to make sure the user gets back from SimpleSAMLphp to Drupal after logout.

Instead we can get the current URL in simplesamlphp_auth_user_logout() and then, if no explicit logout_goto_url has been set, redirect to that URL. We also need to check that we're not on the /user/logout page, since that page will 403 for a logged out user.

Patch attached.

rickward’s picture

George - does your patch work in your instance?

It reads like it would work, but when I use it, I am still getting redirected to \Drupal::config('simplesamlphp_auth.settings')->get('logout_goto_url') in every case (eg, when I kill the session for my SP but leave my Drupal session running).

rickward’s picture

Our use case may differ slightly from @george-bills but I have altered his approach slightly to deal with the issue we experience.

In our case, we want to direct users to a global SSO logout page after they explicitly navigate to /user/logout. However, when users who left their Drupal session open return to the site after their SAML credential has expired, they are unexpectedly redirected to the global SSO logout page rather than the page that they requested (whether or not they have permissions for that page in the anonymous role). This patch updates the implementation of simplesamlphp_auth_user_logout so that if the user has not selected /user/logout, then they are directed to the page they expect.

Additionally, I changed the usage of \Drupal::request()->getRequestUri() to \Drupal::request()->getUri(). getRequestUri yields unexpected behavior on hosts like Pantheon with complex internal networking. getUri preserves the requested port and protocol.

The resulting behavior more closely mirrors that of the 7.x-3.x branch, which our organization found preferable.

rickward’s picture

Status: Active » Needs review

Updating to needs review... apologies if this is not the correct procedure.

mstrelan’s picture

Eduardo Alvarez’s picture

We have a large set of Drupal 8 websites, more than 500, using simplesamlphp_auth module as the base authentication mechanism and we are affected by the same issue explained here. Indeed pretty confusing for users.

Applying patch #4 fixes the issue. Thanks!

Any plan to have it integrated within a future release?

kscheirer’s picture

Status: Needs review » Reviewed & tested by the community

Based on #7.

berdir’s picture

Status: Reviewed & tested by the community » Needs work

Seems like a valid improvement but needs a reroll.

Eduardo Alvarez’s picture

After updating simplesamlphp_auth module to version 8.x-3.2

This patch (#4) seems not valid anymore since we are again observing the issue.

In our environment I'm able to reproduce it by

  • going to a specific path
  • login
  • Manually removing the SimpleSAMLSessionID cookie (to force the behaviour of session expired)
  • Refresh the page

The expected result is to get unauthenticated but still on the same specific path
The observed result is being unauthenticated but redirected to the frontpage (or whatever is defined in the logout page)

Any can comment on this?

Thanks

jedsaet’s picture

Status: Needs work » Needs review
StatusFileSize
new1.19 KB

Straight reroll of #4 against dev.

Eduardo Alvarez’s picture

I've debugged further the issue I've presented on #10

The incompatibility with the present patch started to happen, at least on our enviroment (multisite environment with around 1000 websites), with the release of 3.1, concretely this commit, https://git.drupalcode.org/project/simplesamlphp_auth/-/commit/0990ab0ee...

Basically the problem is that `$simplesaml->isAuthenticated()` returns false when the simplesaml session/cookie expire. So the logic never enters into the IF in order to redirect to the current page when session expires.

This patch takes into account the session expiration case, and properly redirect to the current viewed page when this happen. Tested on our environment.

roderickgadellaabsl’s picture

We're also affected by this issue. Patch #12 works!

kscheirer’s picture

Status: Needs review » Reviewed & tested by the community

Based on #13.

johns996’s picture

I was also experiencing this issue on the multisite I manage. We have about 100 sites and 200+ users authenticating with this module. When a user's session expired they were consistently redirected to our multisite's default landing page which was confusing behavior for most of our non-technical users. Admins on the site generally log in using Drupal's authentication and this redirect issue was never experienced. Comment #12 and the associated patch resolved the issue and no further unwanted redirects are being observed.

mforbes’s picture

johns996’s picture

Commenting here to indicate that #12 is compatible with 4.0.0 running on Drupal 10.1.

mikelutz’s picture

Status: Reviewed & tested by the community » Needs work

I don't think this is the right approach here. Currently the redirect to the base_url isn't happening in the logout hook, it's happening in the event subscriber that checks for session expiry.

  /**
   * Logs out user if not SAML authenticated and local logins are disabled.
   *
   * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
   *   The subscribed event.
   */
  public function checkAuthStatus(RequestEvent $event) {
    if ($this->account->isAnonymous()) {
      return;
    }

    if (!$this->simplesaml->isActivated()) {
      return;
    }

    if ($this->simplesaml->isAuthenticated()) {
      return;
    }

    if ($this->config->get('allow.default_login')) {

      $allowed_uids = explode(',', $this->config->get('allow.default_login_users'));
      if (in_array($this->account->id(), $allowed_uids)) {
        return;
      }

      $allowed_roles = $this->config->get('allow.default_login_roles');
      if (array_intersect($this->account->getRoles(), $allowed_roles)) {
        return;
      }
    }

    if ($this->config->get('debug')) {
      $this->logger->debug('User %name not authorized to log in using local account.', ['%name' => $this->account->getAccountName()]);
    }
    user_logout();

    $response = new RedirectResponse('/', RedirectResponse::HTTP_FOUND);
    $event->setResponse($response);
    $event->stopPropagation();

  }

Since the logout hook no longer redirects when isAuthenticated() returns false, we are falling back to the redirect response to the event here, redirecting back to the homepage. It seems like we should leave the logout hook alone, and handle redirecting on session expiry here in the event. I can also see a need for this to be configurable, or at the very least a bit smarter. If feels like in most cases the user should be redirected to the login page, and then returned to the current url after logging in, though I could see use cases where a site might want to just let them view the page as anonymous without being redirected. I have a need to solve this this week, so I'll open a MR with my solution soon.

mikelutz’s picture

Version: 8.x-3.x-dev » 4.x-dev

pfrenssen’s picture

The current MR !28 will redirect any request to a HTML login page but this will cause problems for requests that accept MIME types other than HTML (e.g. JSON:API / GraphQL / image styles / aggregated CSS files / streamed media / ...)

I think it would be safer to simply reload the page so it is served to the anonymous user. While redirecting a logged out user to the login form is valid in many use cases, it is better to leave this to specialized modules that are better suited to this task (like Redirect 403 to User Login).