From 354631d66a4dd8162bd5d8a07fb1767039de1972 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Thu, 22 Jan 2026 21:54:27 -0500 Subject: [PATCH 1/3] use cookies instead of session --- resources/init.php | 27 ++++++++++-------------- resources/lib/utils.php | 14 +++++++++++++ resources/templates/header.php | 33 +++++++----------------------- resources/templates/home.php | 2 +- test/functional/ViewAsUserTest.php | 1 - 5 files changed, 33 insertions(+), 44 deletions(-) diff --git a/resources/init.php b/resources/init.php index 80d5aea98..6112e11f0 100644 --- a/resources/init.php +++ b/resources/init.php @@ -11,7 +11,6 @@ use UnityWebPortal\lib\UnityUser; use UnityWebPortal\lib\UnityWebhook; use UnityWebPortal\lib\UnityGithub; -use UnityWebPortal\lib\UnityHTTPD; use UnityWebPortal\lib\UserFlag; if (CONFIG["site"]["enable_exception_handler"]) { @@ -55,26 +54,22 @@ } if (isset($_SERVER["REMOTE_USER"])) { - // Check if SSO is enabled on this page + _setcookie("navbar_show_logged_in_user_pages", "true"); $SSO = UnitySSO::getSSO(); - $_SESSION["SSO"] = $SSO; - - $OPERATOR = new UnityUser($SSO["user"], $LDAP, $SQL, $MAILER, $WEBHOOK); - $_SESSION["is_admin"] = $OPERATOR->getFlag(UserFlag::ADMIN); - $_SESSION["OPERATOR"] = $SSO["user"]; $_SESSION["OPERATOR_IP"] = $_SERVER["REMOTE_ADDR"]; - - if (isset($_SESSION["viewUser"]) && $_SESSION["is_admin"]) { + if ( + isset($_SESSION["viewUser"]) && + $LDAP->userFlagGroups["admin"]->memberUIDExists($SSO["user"]) + ) { $USER = new UnityUser($_SESSION["viewUser"], $LDAP, $SQL, $MAILER, $WEBHOOK); } else { - $USER = $OPERATOR; + $USER = new UnityUser($SSO["user"], $LDAP, $SQL, $MAILER, $WEBHOOK); } - - $_SESSION["user_exists"] = $USER->exists(); - $_SESSION["is_pi"] = $USER->isPI(); - - $SQL->addLog("user_login", $OPERATOR->uid); - + _setcookie("navbar_show_admin_pages", $USER->getFlag(UserFlag::ADMIN) ? "true" : "false"); + _setcookie("navbar_show_pi_pages", $USER->isPI() ? "true" : "false"); + $SQL->addLog("user_login", $SSO["user"]); $USER->updateIsQualified(); // in case manual changes have been made to PI groups +} else { + _setcookie("navbar_show_logged_in_user_pages", "false"); } diff --git a/resources/lib/utils.php b/resources/lib/utils.php index b6b96d293..f232baf28 100644 --- a/resources/lib/utils.php +++ b/resources/lib/utils.php @@ -283,3 +283,17 @@ function _curl_exec(CurlHandle $handle): string } return $output; } + +function _setcookie( + string $name, + string $value, + int $ttl_seconds = 600, + string $path = "/", + string $domain = "", + bool $secure = false, + bool $httponly = false, +): void { + setcookie($name, $value, time() + $ttl_seconds, $path, $domain, $secure, $httponly); + // $_COOKIE won't see this change until the next page load, update it now + $_COOKIE[$name] = $value; +} diff --git a/resources/templates/header.php b/resources/templates/header.php index 1426d15c8..209e6a9f4 100644 --- a/resources/templates/header.php +++ b/resources/templates/header.php @@ -5,10 +5,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { // another page should have already validated and we can't validate the same token twice // UnityHTTPD::validatePostCSRFToken(); - if ( - ($_SESSION["is_admin"] ?? false) == true - && ($_POST["form_type"] ?? null) == "clearView" - ) { + if (($_POST["form_type"] ?? null) == "clearView") { unset($_SESSION["viewUser"]); UnityHTTPD::redirect(getURL("admin/user-mgmt.php")); } @@ -21,13 +18,8 @@ UnityHTTPD::redirect(); } -if (isset($SSO)) { - if ( - !$_SESSION["user_exists"] - && !str_ends_with($_SERVER['PHP_SELF'], "/panel/new_account.php") - ) { - UnityHTTPD::redirect(getURL("panel/new_account.php")); - } +if (isset($USER) && !$USER->exists() && !str_ends_with($_SERVER['PHP_SELF'], "/new_account.php")) { + UnityHTTPD::redirect(getURL("panel/new_account.php")); } ?> @@ -100,30 +92,23 @@ CONFIG["menuitems"]["labels"][$i] . "\n"; } - if (isset($_SESSION["user_exists"]) && $_SESSION["user_exists"]) { + if (($_COOKIE["navbar_show_logged_in_user_pages"] ?? "false") === "true") { echo "\n"; - // Menu Items for Present Users echo getHyperlink("Account Settings", "panel/account.php") . "\n"; echo getHyperlink("My PIs", "panel/groups.php") . "\n"; - if (isset($_SESSION["is_pi"]) && $_SESSION["is_pi"]) { - // PI only pages + if (($_COOKIE["navbar_show_pi_pages"] ?? "false") === "true") { echo getHyperlink("My Users", "panel/pi.php") . "\n"; } - // additional branding items $num_additional_items = count(CONFIG["menuitems_secure"]["labels"]); for ($i = 0; $i < $num_additional_items; $i++) { echo "" . CONFIG["menuitems_secure"]["labels"][$i] . "\n"; } - // admin pages - if ( - isset($_SESSION["is_admin"]) && $_SESSION["is_admin"] && !isset($_SESSION["viewUser"]) - ) { + if (($_COOKIE["navbar_show_admin_pages"] ?? "false") === "true") { echo "\n"; - // Admin only pages echo getHyperlink("User Management", "admin/user-mgmt.php") . "\n"; echo getHyperlink("PI Management", "admin/pi-mgmt.php") . "\n"; } @@ -177,11 +162,7 @@ ); } echo ""; - if ( - isset($_SESSION["is_admin"]) - && $_SESSION["is_admin"] - && isset($_SESSION["viewUser"]) - ) { + if (isset($_SESSION["viewUser"])) { $viewUser = $_SESSION["viewUser"]; $CSRFTokenHiddenFormInput = UnityHTTPD::getCSRFTokenHiddenFormInput(); echo " diff --git a/resources/templates/home.php b/resources/templates/home.php index 1af49a8ed..55ce0dafb 100644 --- a/resources/templates/home.php +++ b/resources/templates/home.php @@ -3,7 +3,7 @@ Welcome to the UnityHPC Platform Account Portal. Here you can manage your SSH keys, join and leave PI groups, manage your own PI group, and more. assertEquals($afterUid, $USER->uid); - // $this->assertTrue($_SESSION["user_exists"]); http_post(__DIR__ . "/../../webroot/panel/account.php", [ "form_type" => "clearView", ]); From 77d7b039fac8905bb5ceb1afd19e25ab277c0e16 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Thu, 22 Jan 2026 21:55:42 -0500 Subject: [PATCH 2/3] avoid test case pollution --- test/phpunit-bootstrap.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index 0d3b02498..4cdc517f1 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -72,6 +72,7 @@ function http_post(string $phpfile, array $post_data, bool $do_generate_csrf_tok { global $LDAP, $SQL, $MAILER, $WEBHOOK, $GITHUB, $SITE, $SSO, $USER, $LOC_HEADER, $LOC_FOOTER; $_PREVIOUS_SERVER = $_SERVER; + $_PREVIOUS_COOKIE = $_COOKIE; $_SERVER["REQUEST_METHOD"] = "POST"; $_SERVER["PHP_SELF"] = _preg_replace("/.*webroot\//", "/", $phpfile); $_SERVER["REQUEST_URI"] = _preg_replace("/.*webroot\//", "/", $phpfile); // Slightly imprecise because it doesn't include get parameters @@ -96,6 +97,7 @@ function http_post(string $phpfile, array $post_data, bool $do_generate_csrf_tok } finally { unset($_POST); $_SERVER = $_PREVIOUS_SERVER; + $_COOKIE = $_PREVIOUS_COOKIE; } } @@ -103,6 +105,7 @@ function http_get(string $phpfile, array $get_data = [], bool $ignore_die = fals { global $LDAP, $SQL, $MAILER, $WEBHOOK, $GITHUB, $SITE, $SSO, $USER, $LOC_HEADER, $LOC_FOOTER; $_PREVIOUS_SERVER = $_SERVER; + $_PREVIOUS_COOKIE = $_COOKIE; $_SERVER["REQUEST_METHOD"] = "GET"; $_SERVER["PHP_SELF"] = _preg_replace("/.*webroot\//", "/", $phpfile); $_SERVER["REQUEST_URI"] = _preg_replace("/.*webroot\//", "/", $phpfile); // Slightly imprecise because it doesn't include get parameters @@ -124,6 +127,7 @@ function http_get(string $phpfile, array $get_data = [], bool $ignore_die = fals } finally { unset($_GET); $_SERVER = $_PREVIOUS_SERVER; + $_COOKIE = $_PREVIOUS_COOKIE; } } From 8dead44026a581a43a022d790ade24199e3b9357 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Thu, 22 Jan 2026 21:56:57 -0500 Subject: [PATCH 3/3] don't unset logged in cookie --- resources/init.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/resources/init.php b/resources/init.php index 6112e11f0..01c390ed0 100644 --- a/resources/init.php +++ b/resources/init.php @@ -70,6 +70,4 @@ _setcookie("navbar_show_pi_pages", $USER->isPI() ? "true" : "false"); $SQL->addLog("user_login", $SSO["user"]); $USER->updateIsQualified(); // in case manual changes have been made to PI groups -} else { - _setcookie("navbar_show_logged_in_user_pages", "false"); }