From bc8d4abb0d03184dc0d3a84b7fa70e2cf9274007 Mon Sep 17 00:00:00 2001 From: Pascal Seeland Date: Sun, 29 Oct 2023 06:31:33 +0100 Subject: [PATCH] Fix 31639: redirect loop when session expireds --- .../classes/class.ilSession.php | 22 ++++++++++++++----- .../Init/classes/class.ilInitialisation.php | 13 +++++++---- Services/Init/classes/class.ilStartUpGUI.php | 2 +- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Services/Authentication/classes/class.ilSession.php b/Services/Authentication/classes/class.ilSession.php index 969d658af767..69eb46c19dce 100755 --- a/Services/Authentication/classes/class.ilSession.php +++ b/Services/Authentication/classes/class.ilSession.php @@ -1,7 +1,5 @@ * @@ -226,9 +226,9 @@ public static function _exists(string $a_session_id): bool /** * Destroy session * - * @param string|array session id|s - * @param int closing context - * @param int|bool expired at timestamp + * @param string|array $a_session_id session id|s + * @param int|null $a_closing_context closing context + * @param int|bool $a_expired_at expired at timestamp */ public static function _destroy($a_session_id, ?int $a_closing_context = null, $a_expired_at = null): bool { @@ -258,6 +258,18 @@ public static function _destroy($a_session_id, ?int $a_closing_context = null, $ $ilDB->manipulate($q); + try { + // only delete session cookie if it is set in the current request + if ($DIC->http()->wrapper()->cookie()->has(session_name()) && + $DIC->http()->wrapper()->cookie()->retrieve(session_name(), $DIC->refinery()->kindlyTo()->string()) === $a_session_id) { + $cookieJar = $DIC->http()->cookieJar()->without(session_name()); + $cookieJar->renderIntoResponseHeader($DIC->http()->response()); + } + } catch (\Throwable $e) { + // ignore + // this is needed for "header already" sent errors when the random cleanup of expired sessions is triggered + } + return true; } diff --git a/Services/Init/classes/class.ilInitialisation.php b/Services/Init/classes/class.ilInitialisation.php index f48fdb0d5c17..771d86e646cd 100644 --- a/Services/Init/classes/class.ilInitialisation.php +++ b/Services/Init/classes/class.ilInitialisation.php @@ -1,4 +1,5 @@ debug('Redirecting to login page.'); if ($DIC['ilAuthSession']->isExpired()) { ilSession::setClosingContext(ilSession::SESSION_CLOSE_EXPIRE); + $session_expired = true; } if (!$DIC['ilAuthSession']->isAuthenticated()) { ilSession::setClosingContext(ilSession::SESSION_CLOSE_LOGIN); @@ -999,8 +1001,8 @@ protected static function goToLogin(): void ]) ); - $script = "login.php?" . $target . "client_id=" . $client_id . - "&auth_stat=" . $a_auth_stat; + $script = "login.php?" . $target . "client_id=" . $client_id; + $script .= $session_expired ? "&session_expired=1" : ""; self::redirect( $script, @@ -1373,6 +1375,10 @@ public static function resumeUserSession(): void !$DIC['ilAuthSession']->isAuthenticated() or $DIC['ilAuthSession']->isExpired() ) { + if ($GLOBALS['DIC']['ilAuthSession']->isExpired()) { + ilSession::_destroy($_COOKIE[session_name()], ilSession::SESSION_CLOSE_EXPIRE); + } + ilLoggerFactory::getLogger('init')->debug('Current session is invalid: ' . $GLOBALS['DIC']['ilAuthSession']->getId()); $current_script = substr(strrchr($_SERVER["PHP_SELF"], "/"), 1); if (self::blockedAuthentication($current_script)) { @@ -1468,7 +1474,6 @@ private static function initGlobalScreen(\ILIAS\DI\Container $c): void }; $c->globalScreen()->tool()->context()->stack()->clear(); $c->globalScreen()->tool()->context()->claim()->main(); -// $c->globalScreen()->tool()->context()->current()->addAdditionalData('DEVMODE', (bool) DEVMODE); } /** diff --git a/Services/Init/classes/class.ilStartUpGUI.php b/Services/Init/classes/class.ilStartUpGUI.php index b762260792c4..e93042b2eb38 100755 --- a/Services/Init/classes/class.ilStartUpGUI.php +++ b/Services/Init/classes/class.ilStartUpGUI.php @@ -308,7 +308,7 @@ protected function showLoginPage(ilPropertyFormGUI $form = null): void $page_editor_html = $this->purgePlaceholders($page_editor_html); // check expired session and send message - if ($this->authSession->isExpired()) { + if ($this->authSession->isExpired() || $this->http->wrapper()->query()->has('session_expired')) { $this->mainTemplate->setOnScreenMessage('failure', $this->lng->txt('auth_err_expired')); } elseif ($this->http->wrapper()->query()->has('reg_confirmation_msg')) { $this->lng->loadLanguageModule('registration');