diff --git a/login.php b/login.php index 125fd491..242c1371 100644 --- a/login.php +++ b/login.php @@ -42,6 +42,9 @@ require_once "includes/inc_set_timezone.php"; $session_ip = sanitizeInput(getIP()); $session_user_agent = sanitizeInput($_SERVER['HTTP_USER_AGENT'] ?? ''); +// IMPORTANT (Option B support): ensure this exists in this scope so logAction() can use it +$session_user_id = intval($_SESSION['user_id'] ?? 0); + $row = mysqli_fetch_assoc(mysqli_query( $mysqli, "SELECT COUNT(log_id) AS failed_login_count @@ -54,6 +57,7 @@ $row = mysqli_fetch_assoc(mysqli_query( $failed_login_count = intval($row['failed_login_count']); if ($failed_login_count >= 15) { + // Make sure global session_user_id is not required here (will be 0 anyway) logAction("Login", "Blocked", "$session_ip was blocked access to login due to IP lockout"); header("HTTP/1.1 429 Too Many Requests"); exit("

$config_app_name

Your IP address has been blocked due to repeated failed login attempts. Please try again later.

This action has been logged."); @@ -237,7 +241,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_ if ($agentRow === null && $clientRow === null) { header("HTTP/1.1 401 Unauthorized"); + + // Option B not possible here (we don't know user_id reliably) logAction("Login", "Failed", "Failed login attempt using $email"); + $response = "
Incorrect username or password. @@ -274,12 +281,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_ } $_SESSION['pending_dual_login'] = [ - 'email' => $email, - 'agent_user_id' => intval($agentRow['user_id']), - 'client_user_id' => intval($clientRow['user_id']), + 'email' => $email, + 'agent_user_id' => intval($agentRow['user_id']), + 'client_user_id' => intval($clientRow['user_id']), 'agent_master_key' => $agent_master_key, // may be null - 'token' => $pending_token, - 'created' => time() + 'token' => $pending_token, + 'created' => time() ]; } } @@ -373,7 +380,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_ $extended_log .= ", generated a new remember-me token"; } - // Suspicious login checks / email notify (kept from your code) + // Suspicious login checks / email notify $sql_ip_prev_logins = mysqli_fetch_assoc(mysqli_query($mysqli, " SELECT COUNT(log_id) AS ip_previous_logins FROM logs @@ -409,6 +416,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_ addToMailQueue($data); } + // Option B: set session_user_id BEFORE logAction() + $session_user_id = $user_id; logAction("Login", "Success", "$user_name successfully logged in $extended_log", 0, $user_id); $_SESSION['user_id'] = $user_id; @@ -419,7 +428,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_ $config_start_page = "user/mfa_enforcement.php"; } - // ✅ Setup encryption session key WITHOUT PASSWORD IN SESSION + // Setup encryption session key WITHOUT PASSWORD IN SESSION // If we are coming from MFA step, master key is in pending_mfa_login. // If we are coming from login step with no MFA, decrypt now. $site_encryption_master_key = null; @@ -468,11 +477,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_ } $_SESSION['pending_mfa_login'] = [ - 'email' => $user_email, - 'agent_user_id' => $user_id, - 'agent_master_key'=> $agent_master_key, // may be null - 'token' => $pending_mfa_token, - 'created' => time() + 'email' => $user_email, + 'agent_user_id' => $user_id, + 'agent_master_key' => $agent_master_key, // may be null + 'token' => $pending_mfa_token, + 'created' => time() ]; $token_field = " @@ -488,6 +497,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_
"; if ($current_code !== 0) { + + // Option B: set session_user_id BEFORE logAction() + $session_user_id = $user_id; logAction("Login", "MFA Failed", "$user_email failed MFA", 0, $user_id); if (!empty($config_smtp_host)) { @@ -518,17 +530,25 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_ if ($config_client_portal_enable != 1) { header("HTTP/1.1 401 Unauthorized"); + logAction("Client Login", "Failed", "Client portal disabled; login attempt using $email"); + $response = "
Incorrect username or password.
"; } else { - $user_id = intval($selectedRow['contact_user_id']); - $client_id = intval($selectedRow['contact_client_id']); - $contact_id = intval($selectedRow['contact_id']); - $user_auth_method = sanitizeInput($selectedRow['user_auth_method']); + // Client login user id can be clobbered by SELECT users.*, contacts.*, clients.* collisions. + // Prefer contact_user_id (ties to the portal user), fallback to user_id if present. + $user_id = intval($selectedRow['contact_user_id'] ?? 0); + if ($user_id === 0) { + $user_id = intval($selectedRow['user_id'] ?? 0); + } + + $client_id = intval($selectedRow['contact_client_id'] ?? 0); + $contact_id = intval($selectedRow['contact_id'] ?? 0); + $user_auth_method = sanitizeInput($selectedRow['user_auth_method'] ?? ''); if ($client_id && $contact_id && $user_auth_method === 'local') { @@ -539,6 +559,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_ $_SESSION['contact_id'] = $contact_id; $_SESSION['login_method'] = "local"; + // Keep consistent with agent flow (helps any shared session checks) + $_SESSION['logged'] = true; + $_SESSION['csrf_token'] = randomString(32); + + // Option B: set session_user_id BEFORE logAction() + $session_user_id = $user_id; logAction("Client Login", "Success", "Client contact $user_email successfully logged in locally", $client_id, $user_id); header("Location: client/index.php"); @@ -546,7 +572,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && (isset($_POST['login']) || isset($_ } else { - logAction("Client Login", "Failed", "Failed client portal login attempt using $email (invalid auth method or missing contact/client)", $client_id ?? 0, $user_id); + // if we have a users.user_id, log it + $session_user_id = $user_id ?: 0; + logAction( + "Client Login", + "Failed", + "Failed client portal login attempt using $email (invalid auth method or missing contact/client)", + $client_id ?? 0, + $user_id + ); header("HTTP/1.1 401 Unauthorized"); $response = "