mirror of
https://github.com/itflow-org/itflow
synced 2026-08-16 12:35:11 +00:00
Rotate session ID on login and fix client portal Entra SSO
This commit is contained in:
@@ -5,16 +5,7 @@
|
|||||||
* Checks if the client is logged in or not
|
* Checks if the client is logged in or not
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!isset($_SESSION)) {
|
require_once __DIR__ . "/../../includes/session_init.php";
|
||||||
// HTTP Only cookies
|
|
||||||
ini_set("session.cookie_httponly", true);
|
|
||||||
ini_set("session.cookie_samesite", "Lax");
|
|
||||||
if ($config_https_only) {
|
|
||||||
// Tell client to only send cookie(s) over HTTPS
|
|
||||||
ini_set("session.cookie_secure", true);
|
|
||||||
}
|
|
||||||
session_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($_SESSION['client_logged_in']) || !$_SESSION['client_logged_in']) {
|
if (!isset($_SESSION['client_logged_in']) || !$_SESSION['client_logged_in']) {
|
||||||
redirect("/login.php");
|
redirect("/login.php");
|
||||||
|
|||||||
@@ -7,16 +7,7 @@
|
|||||||
require_once '../config.php';
|
require_once '../config.php';
|
||||||
require_once '../functions.php';
|
require_once '../functions.php';
|
||||||
|
|
||||||
if (!isset($_SESSION)) {
|
require_once __DIR__ . "/../includes/session_init.php";
|
||||||
// HTTP Only cookies
|
|
||||||
ini_set("session.cookie_httponly", true);
|
|
||||||
ini_set("session.cookie_samesite", "Lax");
|
|
||||||
if ($config_https_only) {
|
|
||||||
// Tell client to only send cookie(s) over HTTPS
|
|
||||||
ini_set("session.cookie_secure", true);
|
|
||||||
}
|
|
||||||
session_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set Timezone after session starts
|
// Set Timezone after session starts
|
||||||
require_once "../includes/inc_set_timezone.php";
|
require_once "../includes/inc_set_timezone.php";
|
||||||
@@ -38,27 +29,60 @@ $token_grant_url = "https://login.microsoftonline.com/organizations/oauth2/v2.0/
|
|||||||
|
|
||||||
// Initial Login Request, via Microsoft
|
// Initial Login Request, via Microsoft
|
||||||
// Returns an authorization code if login was successful
|
// Returns an authorization code if login was successful
|
||||||
if ($_SERVER['REQUEST_METHOD'] == "GET") {
|
if ($_SERVER['REQUEST_METHOD'] == "GET" && !isset($_GET['code']) && !isset($_GET['error'])) {
|
||||||
|
|
||||||
|
// Single-use random state held server side. Never the session ID - that
|
||||||
|
// would put it in the URL, browser history and Microsoft's logs.
|
||||||
|
try {
|
||||||
|
$state = bin2hex(random_bytes(32));
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$state = sha1(uniqid((string) mt_rand(), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SESSION['azure_oauth_state'] = $state;
|
||||||
|
$_SESSION['azure_oauth_state_expires_at'] = time() + 600;
|
||||||
|
|
||||||
$params = array (
|
$params = array (
|
||||||
'client_id' => $client_id,
|
'client_id' => $client_id,
|
||||||
'redirect_uri' => $redirect_uri,
|
'redirect_uri' => $redirect_uri,
|
||||||
'response_type' => 'code',
|
'response_type' => 'code',
|
||||||
'response_mode' =>'form_post',
|
// Must come back as a top-level GET - a SameSite=Lax session cookie is
|
||||||
|
// not sent on the cross-site POST that form_post produces
|
||||||
|
'response_mode' => 'query',
|
||||||
'scope' => 'https://graph.microsoft.com/User.Read',
|
'scope' => 'https://graph.microsoft.com/User.Read',
|
||||||
'state' => session_id());
|
'state' => $state);
|
||||||
|
|
||||||
header('Location: '.$auth_code_url.'?'.http_build_query($params));
|
header('Location: '.$auth_code_url.'?'.http_build_query($params));
|
||||||
|
exit();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login was successful, Microsoft has returned us an authorization code via POST
|
// Microsoft has redirected back with an authorization code (or an error)
|
||||||
// Request an access token using authorization code (& client secret) (server side)
|
// Request an access token using authorization code (& client secret) (server side)
|
||||||
if (isset($_POST['code']) && $_POST['state'] == session_id()) {
|
if (isset($_GET['code']) || isset($_GET['error'])) {
|
||||||
|
|
||||||
|
$state = is_string($_GET['state'] ?? null) ? $_GET['state'] : '';
|
||||||
|
$session_state = $_SESSION['azure_oauth_state'] ?? '';
|
||||||
|
$session_state_expires = intval($_SESSION['azure_oauth_state_expires_at'] ?? 0);
|
||||||
|
|
||||||
|
// Single use, consumed whether or not it validates
|
||||||
|
unset($_SESSION['azure_oauth_state'], $_SESSION['azure_oauth_state_expires_at']);
|
||||||
|
|
||||||
|
if (!empty($_GET['error'])) {
|
||||||
|
$_SESSION['login_message'] = 'Something went wrong with logging you in: Microsoft returned an error. Please try again.';
|
||||||
|
header("Location: ../login.php");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($state) || empty($session_state) || !hash_equals($session_state, $state) || time() > $session_state_expires) {
|
||||||
|
$_SESSION['login_message'] = 'Something went wrong with logging you in: the sign-in request could not be verified. Please try again.';
|
||||||
|
header("Location: ../login.php");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
$params = array (
|
$params = array (
|
||||||
'client_id' =>$client_id,
|
'client_id' =>$client_id,
|
||||||
'code' => $_POST['code'],
|
'code' => is_string($_GET['code'] ?? null) ? $_GET['code'] : '',
|
||||||
'redirect_uri' => $redirect_uri,
|
'redirect_uri' => $redirect_uri,
|
||||||
'grant_type' => 'authorization_code',
|
'grant_type' => 'authorization_code',
|
||||||
'client_secret' => $client_secret
|
'client_secret' => $client_secret
|
||||||
@@ -93,8 +117,9 @@ if (isset($_POST['code']) && $_POST['state'] == session_id()) {
|
|||||||
|
|
||||||
if (isset($msgraph_response['error'])) {
|
if (isset($msgraph_response['error'])) {
|
||||||
// Something went wrong verifying the token/using the Graph API - quit
|
// Something went wrong verifying the token/using the Graph API - quit
|
||||||
echo "Error with MS Graph API. Details:";
|
error_log("ITFlow: MS Graph API error during client portal Entra login: " . json_encode($msgraph_response['error']));
|
||||||
var_dump($msgraph_response['error']);
|
$_SESSION['login_message'] = 'Something went wrong with logging you in: could not read your profile from Microsoft. Please try again.';
|
||||||
|
header("Location: ../login.php");
|
||||||
exit();
|
exit();
|
||||||
|
|
||||||
} elseif (isset($msgraph_response['id'])) {
|
} elseif (isset($msgraph_response['id'])) {
|
||||||
@@ -121,6 +146,9 @@ if (isset($_POST['code']) && $_POST['state'] == session_id()) {
|
|||||||
|
|
||||||
if ($user_auth_method == 'azure') {
|
if ($user_auth_method == 'azure') {
|
||||||
|
|
||||||
|
// New session ID for the authenticated session (CWE-384)
|
||||||
|
session_regenerate_id(true);
|
||||||
|
|
||||||
$_SESSION['client_logged_in'] = true;
|
$_SESSION['client_logged_in'] = true;
|
||||||
$_SESSION['client_id'] = $client_id;
|
$_SESSION['client_id'] = $client_id;
|
||||||
$_SESSION['user_id'] = $user_id;
|
$_SESSION['user_id'] = $user_id;
|
||||||
@@ -138,22 +166,27 @@ if (isset($_POST['code']) && $_POST['state'] == session_id()) {
|
|||||||
|
|
||||||
$_SESSION['login_message'] = 'Something went wrong with logging you in: Your account is not configured for Entra SSO. Please ensure you are setup in ITFlow as a contact and have Entra SSO configured.';
|
$_SESSION['login_message'] = 'Something went wrong with logging you in: Your account is not configured for Entra SSO. Please ensure you are setup in ITFlow as a contact and have Entra SSO configured.';
|
||||||
|
|
||||||
header("Location: index.php");
|
header("Location: ../login.php");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
header('Location: index.php');
|
header('Location: index.php');
|
||||||
|
exit();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
echo "Error getting access_token";
|
error_log("ITFlow: no access_token returned during client portal Entra login");
|
||||||
|
$_SESSION['login_message'] = 'Something went wrong with logging you in: Microsoft did not return an access token. Please try again.';
|
||||||
|
header("Location: ../login.php");
|
||||||
|
exit();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user is just sat on the page, redirect them to log in to try again
|
// If the user is just sat on the page, send them back to log in to try again
|
||||||
if (empty($_GET)) {
|
header("Location: ../login.php");
|
||||||
echo "<script> setTimeout(function() { window.location = \"login.php\"; },1000);</script>";
|
exit();
|
||||||
}
|
|
||||||
|
|||||||
@@ -22,16 +22,7 @@ if($config_client_portal_enable == 0) {
|
|||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($_SESSION)) {
|
require_once __DIR__ . "/../includes/session_init.php";
|
||||||
// HTTP Only cookies
|
|
||||||
ini_set("session.cookie_httponly", true);
|
|
||||||
ini_set("session.cookie_samesite", "Lax");
|
|
||||||
if ($config_https_only) {
|
|
||||||
// Tell client to only send cookie(s) over HTTPS
|
|
||||||
ini_set("session.cookie_secure", true);
|
|
||||||
}
|
|
||||||
session_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set Timezone after session
|
// Set Timezone after session
|
||||||
require_once "../includes/inc_set_timezone.php";
|
require_once "../includes/inc_set_timezone.php";
|
||||||
|
|||||||
@@ -4,12 +4,7 @@ require_once "../config.php";
|
|||||||
require_once "../functions.php";
|
require_once "../functions.php";
|
||||||
require_once "../includes/load_global_settings.php";
|
require_once "../includes/load_global_settings.php";
|
||||||
|
|
||||||
ini_set("session.cookie_httponly", true);
|
require_once __DIR__ . "/../includes/session_init.php";
|
||||||
ini_set("session.cookie_samesite", "Lax");
|
|
||||||
if ($config_https_only) {
|
|
||||||
ini_set("session.cookie_secure", true);
|
|
||||||
}
|
|
||||||
session_start();
|
|
||||||
|
|
||||||
require_once "../includes/inc_set_timezone.php"; // Must be included after session_start to work
|
require_once "../includes/inc_set_timezone.php"; // Must be included after session_start to work
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
if (!isset($_SESSION)) {
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
// HTTP Only cookies
|
// HTTP Only cookies
|
||||||
ini_set("session.cookie_httponly", true);
|
ini_set("session.cookie_httponly", true);
|
||||||
ini_set("session.cookie_samesite", "Lax");
|
ini_set("session.cookie_samesite", "Lax");
|
||||||
|
|
||||||
if ($config_https_only) {
|
// Refuse to adopt a session ID the server never issued
|
||||||
|
ini_set("session.use_strict_mode", 1);
|
||||||
|
|
||||||
|
if (!isset($config_https_only) || $config_https_only) {
|
||||||
// Tell client to only send cookie(s) over HTTPS
|
// Tell client to only send cookie(s) over HTTPS
|
||||||
ini_set("session.cookie_secure", true);
|
ini_set("session.cookie_secure", true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,5 @@
|
|||||||
|
|
||||||
require_once __DIR__ . "/config.php";
|
require_once __DIR__ . "/config.php";
|
||||||
|
|
||||||
ini_set("session.cookie_httponly", true);
|
require_once __DIR__ . "/includes/session_init.php";
|
||||||
ini_set("session.cookie_samesite", "Lax");
|
|
||||||
if ($config_https_only) {
|
|
||||||
ini_set("session.cookie_secure", true);
|
|
||||||
}
|
|
||||||
session_start();
|
|
||||||
session_write_close();
|
session_write_close();
|
||||||
|
|||||||
22
login.php
22
login.php
@@ -13,16 +13,7 @@ require_once "config.php";
|
|||||||
require_once "functions.php";
|
require_once "functions.php";
|
||||||
require_once "libs/totp/totp.php";
|
require_once "libs/totp/totp.php";
|
||||||
|
|
||||||
if (session_status() === PHP_SESSION_NONE) {
|
require_once __DIR__ . "/includes/session_init.php";
|
||||||
ini_set("session.cookie_httponly", true);
|
|
||||||
ini_set("session.cookie_samesite", "Lax");
|
|
||||||
|
|
||||||
if ($config_https_only || !isset($config_https_only)) {
|
|
||||||
ini_set("session.cookie_secure", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
session_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($config_enable_setup) || $config_enable_setup == 1) {
|
if (!isset($config_enable_setup) || $config_enable_setup == 1) {
|
||||||
header("Location: /setup");
|
header("Location: /setup");
|
||||||
@@ -442,6 +433,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_
|
|||||||
$session_user_id = $user_id;
|
$session_user_id = $user_id;
|
||||||
logAudit("Login", "Success", "$user_name successfully logged in $extended_log", 0, $user_id);
|
logAudit("Login", "Success", "$user_name successfully logged in $extended_log", 0, $user_id);
|
||||||
|
|
||||||
|
// New session ID for the authenticated session (CWE-384)
|
||||||
|
session_regenerate_id(true);
|
||||||
|
|
||||||
$_SESSION['user_id'] = $user_id;
|
$_SESSION['user_id'] = $user_id;
|
||||||
$_SESSION['csrf_token'] = randomString(32);
|
$_SESSION['csrf_token'] = randomString(32);
|
||||||
$_SESSION['logged'] = true;
|
$_SESSION['logged'] = true;
|
||||||
@@ -607,6 +601,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_
|
|||||||
|
|
||||||
if ($client_id && $contact_id && $user_auth_method === 'local') {
|
if ($client_id && $contact_id && $user_auth_method === 'local') {
|
||||||
|
|
||||||
|
// New session ID for the authenticated session (CWE-384)
|
||||||
|
session_regenerate_id(true);
|
||||||
|
|
||||||
$_SESSION['client_logged_in'] = true;
|
$_SESSION['client_logged_in'] = true;
|
||||||
$_SESSION['client_id'] = $client_id;
|
$_SESSION['client_id'] = $client_id;
|
||||||
$_SESSION['user_id'] = $user_id;
|
$_SESSION['user_id'] = $user_id;
|
||||||
@@ -694,6 +691,11 @@ $show_login_form = (!$show_role_choice && !$show_mfa_form);
|
|||||||
<p class="login-box-msg px-0"><?php echo nl2br($config_login_message); ?></p>
|
<p class="login-box-msg px-0"><?php echo nl2br($config_login_message); ?></p>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
|
<?php if (!empty($_SESSION['login_message'])) { ?>
|
||||||
|
<div class="alert alert-danger"><?php echo escapeHtml($_SESSION['login_message']); ?></div>
|
||||||
|
<?php unset($_SESSION['login_message']); ?>
|
||||||
|
<?php } ?>
|
||||||
|
|
||||||
<?php if (isset($response)) { ?>
|
<?php if (isset($response)) { ?>
|
||||||
<p><?php echo $response; ?></p>
|
<p><?php echo $response; ?></p>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|||||||
Reference in New Issue
Block a user