Add proper session management (CSRF, secure cookies, session tracking)

Co-authored-by: naielv <109038805+naielv@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-07 19:33:13 +00:00
parent b3a2795d66
commit c21dfad437
5 changed files with 43 additions and 3 deletions

View File

@@ -0,0 +1,12 @@
<?php
require_once "tools.session.php";
require_once "tools.security.php";
$redir = safe_redir($_GET["redir"] ?? "/");
$cookie_options_expired = ["expires" => time() - 3600, "path" => "/", "httponly" => true, "secure" => true, "samesite" => "Lax"];
setcookie("auth_user", "", $cookie_options_expired);
setcookie("auth_pass_b64", "", $cookie_options_expired);
session_unset();
session_destroy();
header("Location: $redir");
die();

View File

@@ -39,6 +39,9 @@ if (($_SESSION["auth_ok"] ?? false) != true
$_SESSION["auth_user"] = $username;
$_SESSION["auth_data"] = db_build_auth_data($row);
$_SESSION["auth_ok"] = true;
if (empty($_SESSION["session_created"])) {
$_SESSION["session_created"] = time();
}
init_active_org($_SESSION["auth_data"]);
}
}

View File

@@ -1,4 +1,9 @@
<?php
session_start([ 'cookie_lifetime' => 604800 ]);
ini_set("session.use_only_cookies", "true");
ini_set("session.use_trans_sid", "false");
ini_set("session.use_only_cookies", "1");
ini_set("session.use_trans_sid", "0");
session_start([
'cookie_lifetime' => 604800,
'cookie_httponly' => true,
'cookie_secure' => true,
'cookie_samesite' => 'Lax',
]);

View File

@@ -98,6 +98,7 @@ if (($_GET["google_callback"] ?? "") === "1") {
$_SESSION['auth_user'] = $username;
$_SESSION['auth_data'] = db_build_auth_data($user_row);
$_SESSION['auth_ok'] = true;
$_SESSION['session_created'] = time();
init_active_org($_SESSION['auth_data']);
$cookie_options = ["expires" => time() + (86400 * 30), "path" => "/", "httponly" => true, "secure" => true, "samesite" => "Lax"];
setcookie("auth_user", $username, $cookie_options);
@@ -141,11 +142,13 @@ if (($_GET["logout"] ?? "") === "1") {
$cookie_options_expired = ["expires" => time() - 3600, "path" => "/", "httponly" => true, "secure" => true, "samesite" => "Lax"];
setcookie("auth_user", "", $cookie_options_expired);
setcookie("auth_pass_b64", "", $cookie_options_expired);
session_unset();
session_destroy();
header("Location: $redir");
die();
}
if (($_GET["clear_session"] ?? "") === "1") {
session_unset();
session_destroy();
$redir = safe_redir($_GET["redir"] ?? "/");
header("Location: $redir");
@@ -154,6 +157,11 @@ if (($_GET["clear_session"] ?? "") === "1") {
if (isset($_POST["user"])) {
$user = trim(strtolower($_POST["user"]));
$password = $_POST["password"];
// Validate CSRF token
$csrf_token = $_POST["_csrf"] ?? "";
if (!$csrf_token || !isset($_SESSION["login_csrf"]) || !hash_equals($_SESSION["login_csrf"], $csrf_token)) {
$_GET["_result"] = "Token de seguridad inválido. Por favor, recarga la página e inténtalo de nuevo.";
} else {
$row = db_get_user($user);
if (!$row || !isset($row["password_hash"])) {
$_GET["_result"] = "El usuario no existe.";
@@ -162,6 +170,7 @@ if (isset($_POST["user"])) {
$_SESSION['auth_user'] = $user;
$_SESSION['auth_data'] = db_build_auth_data($row);
$_SESSION['auth_ok'] = true;
$_SESSION['session_created'] = time();
init_active_org($_SESSION['auth_data']);
$cookie_options = ["expires" => time() + (86400 * 30), "path" => "/", "httponly" => true, "secure" => true, "samesite" => "Lax"];
setcookie("auth_user", $user, $cookie_options);
@@ -173,14 +182,19 @@ if (isset($_POST["user"])) {
$_GET["_result"] = "La contraseña no es correcta.";
}
}
}
if (strval(db_get_config('installed')) !== '1') {
header("Location: /_install.php");
die();
}
if (empty($_SESSION["login_csrf"])) {
$_SESSION["login_csrf"] = bin2hex(random_bytes(32));
}
require_once "_incl/pre-body.php";
?>
<form method="post" action="?redir=<?= urlencode($_GET["redir"] ?? "/") ?>">
<input type="hidden" name="_csrf" value="<?= htmlspecialchars($_SESSION["login_csrf"]) ?>">
<div class="card pad" style="max-width: 500px;">
<h1 style="text-align: center;">Iniciar sesión en Axia4</h1>
<div>

View File

@@ -122,6 +122,12 @@ if ($initials === '') {
<div class="info-row"><span class="label">ID Sesión</span><span style="font-family:monospace;font-size:.75rem;"><?= htmlspecialchars(substr(session_id(), 0, 12)) ?>…</span></div>
<div class="info-row"><span class="label">Org. activa</span><span><?= htmlspecialchars($activeOrganization ?: '') ?></span></div>
<div class="info-row"><span class="label">Autenticación</span><span><?= empty($authData['google_auth']) ? 'Contraseña' : 'Google' ?></span></div>
<?php if (!empty($_SESSION['session_created'])): ?>
<div class="info-row"><span class="label">Sesión iniciada</span><span><?= htmlspecialchars(date('d/m/Y H:i', $_SESSION['session_created'])) ?></span></div>
<?php endif; ?>
<?php if (!empty($_SESSION['last_reload_time'])): ?>
<div class="info-row"><span class="label">Última actividad</span><span><?= htmlspecialchars(date('d/m/Y H:i', $_SESSION['last_reload_time'])) ?></span></div>
<?php endif; ?>
<div style="margin-top:16px;">
<a href="/_incl/logout.php" class="btn btn-danger btn-sm">Cerrar sesión</a>
</div>