diff --git a/ecrire/action/logout.php b/ecrire/action/logout.php
index 6c4253997ea7ae02456ba4174f4fd9f09ec37212..60077c2601f894c8a9931e923b0ef9b49617eeed 100644
--- a/ecrire/action/logout.php
+++ b/ecrire/action/logout.php
@@ -72,7 +72,7 @@ function action_logout_dist() {
 		if (isset($_COOKIE['spip_session'])) {
 			$session = charger_fonction('session', 'inc');
 			$session($GLOBALS['visiteur_session']['id_auteur']);
-			spip_setcookie('spip_session', $_COOKIE['spip_session'], time() - 3600, httponly: true);
+			set_cookie_session(false);
 		}
 		// si authentification http, et que la personne est loge,
 		// pour se deconnecter, il faut proposer un nouveau formulaire de connexion http
diff --git a/ecrire/inc/session.php b/ecrire/inc/session.php
index c9499cb704f5260c31ccb5c08d6892d80741548a..9a8907ba9a11ce1acfc3ba0cdec35799259bd64c 100644
--- a/ecrire/inc/session.php
+++ b/ecrire/inc/session.php
@@ -172,7 +172,7 @@ function ajouter_session($auteur) {
 
 	if ((!$cookie = lire_cookie_session()) || intval($cookie) !== $id_auteur
 	) {
-		$cookie = $_COOKIE['spip_session'] = $id_auteur . '_' . md5(uniqid(random_int(0, mt_getrandmax()), true));
+		$cookie = $id_auteur . '_' . md5(uniqid(random_int(0, mt_getrandmax()), true));
 	}
 
 	// Maintenant on sait qu'on a des choses à écrire
@@ -218,7 +218,7 @@ function ajouter_session($auteur) {
 	// poser le cookie de session SPIP
 	include_spip('inc/cookie');
 	$duree = definir_duree_cookie_session($auteur);
-	spip_setcookie('spip_session', $cookie, time() + $duree, httponly: true);
+	$cookie = set_cookie_session($cookie, time() + $duree);
 	spip_log("ajoute session $fichier_session cookie $duree", 'session');
 
 	// Si on est admin, poser le cookie de correspondance
@@ -271,7 +271,11 @@ function definir_duree_cookie_session($auteur) {
 	return (int)(_RENOUVELLE_ALEA * $coef);
 }
 
-function lire_cookie_session() {
+/**
+ * Lire le cookie de session et le valider de façon centralisée
+ * @return false|mixed
+ */
+function lire_cookie_session($accepter_test = false) {
 	static $cookie_valide = [];
 	// pas de cookie ?
 	if (!isset($_COOKIE['spip_session'])) {
@@ -279,8 +283,12 @@ function lire_cookie_session() {
 	}
 
 	if (!isset($cookie_valide[$_COOKIE['spip_session']])) {
+		// cookie de test ?
+		if ($accepter_test && $_COOKIE['spip_session'] === 'test_echec_cookie') {
+			return 'test_echec_cookie';
+		}
 		// cookie invalide ?
-		if (!preg_match(",^\d+_[0-9a-f]{32}$,", $_COOKIE['spip_session'])) {
+		elseif (!preg_match(",^\d+_[0-9a-f]{32}$,", $_COOKIE['spip_session'])) {
 			$cookie_valide[$_COOKIE['spip_session']] = false;
 			unset($_COOKIE['spip_session']);
 			return false;
@@ -292,6 +300,37 @@ function lire_cookie_session() {
 	return $cookie_valide[$_COOKIE['spip_session']];
 }
 
+/**
+ * Prolonger/Changer la valeur/annuler le cookie de session
+ * @param string|false|null $valeur_cookie
+ *   nouveau cookie (string), reset (false), prolonger le cookie existant (null)
+ * @param int $expires
+ *   timestamp d'expiration
+ * @return false|string
+ */
+function set_cookie_session($valeur_cookie = null, int $expires = 0) {
+	if (is_null($valeur_cookie)) {
+		$valeur_cookie = lire_cookie_session();
+	}
+	else {
+		// verifier que la valeur est bien valide
+		$_COOKIE['spip_session'] = $valeur_cookie;
+		$valeur_cookie = lire_cookie_session();
+	}
+	if (!$valeur_cookie) {
+		// supprimer le cookie
+		if (isset($_COOKIE['spip_session'])) {
+			spip_setcookie('spip_session', '', time() - 24 * 3600, httponly: true);
+		}
+		unset($_COOKIE['spip_session']);
+	}
+	else {
+		// set le cookie
+		spip_setcookie('spip_session', $valeur_cookie, $expires, httponly: true);
+	}
+	return $valeur_cookie;
+}
+
 /**
  * Vérifie si le cookie spip_session indique une session valide
  *
diff --git a/ecrire/inc/utils.php b/ecrire/inc/utils.php
index e36dd88e76d1f4868cdf18612a5871538a4eee14..2dbebd52f3df641f44197372ee3cb99525b1c734 100644
--- a/ecrire/inc/utils.php
+++ b/ecrire/inc/utils.php
@@ -3269,14 +3269,14 @@ function lang_select($lang = null) {
 function spip_session($force = false) {
 	static $session;
 	if ($force || !isset($session)) {
-		$s = pipeline(
-			'definir_session',
-			$GLOBALS['visiteur_session']
-				? serialize($GLOBALS['visiteur_session'])
-				. '_' . @$_COOKIE['spip_session']
-				: ''
-		);
-		$session = $s ? substr(md5($s), 0, 8) : '';
+		$s = '';
+		if (!empty($GLOBALS['visiteur_session'])) {
+			include_spip('inc/session');
+			$cookie = lire_cookie_session();
+			$s = serialize($GLOBALS['visiteur_session']) . '_' . ($cookie ?: '');
+		}
+		$s = pipeline('definir_session', $s);
+		$session = ($s ? substr(md5($s), 0, 8) : '');
 	}
 
 	#spip_log('session: '.$session);
diff --git a/ecrire/prive.php b/ecrire/prive.php
index 8a044c63db6d7ccb9d2049beb0093b05cdacf948..f3571c2ab19e313f1a2e0e3a012e9c86ee821c66 100644
--- a/ecrire/prive.php
+++ b/ecrire/prive.php
@@ -25,7 +25,9 @@ if ($var_auth !== '' && !is_int($var_auth)) {
 	// autrement on insiste
 	if (is_array($var_auth)) {
 		$var_auth = '../?' . $_SERVER['QUERY_STRING'];
-		spip_setcookie('spip_session', $_COOKIE['spip_session'], time() + 3600 * 24 * 14, httponly: true);
+		include_spip('inc/session');
+		// on prolonge le cookie
+		set_cookie_session(null, time() + 3600 * 24 * 14);
 	}
 	include_spip('inc/headers');
 	redirige_formulaire($var_auth);
diff --git a/prive/formulaires/login.php b/prive/formulaires/login.php
index 85ece791fef803108644554c6ea70526d7b4f78f..210565fc0208cce0fd556598dca993cbe2ef4bc7 100644
--- a/prive/formulaires/login.php
+++ b/prive/formulaires/login.php
@@ -177,19 +177,20 @@ function formulaires_login_charger_dist($cible = '', $options = [], $deprecated
  *     - chaîne vide sinon.
  **/
 function login_auth_http() {
-	if (
-		!$GLOBALS['ignore_auth_http']
-		&& _request('var_erreur') == 'cookie'
-		&& (!isset($_COOKIE['spip_session']) || $_COOKIE['spip_session'] != 'test_echec_cookie')
-		&& (preg_match(',apache,', \PHP_SAPI) || preg_match(',^Apache.* PHP,', (string) $_SERVER['SERVER_SOFTWARE']))
-		// Attention dans le cas 'intranet' la proposition de se loger
-		// par auth_http peut conduire a l'echec.
-		&& !(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']))
-	) {
-		return generer_url_action('cookie', '', false, true);
-	} else {
-		return '';
+	if (!$GLOBALS['ignore_auth_http'] && _request('var_erreur') == 'cookie') {
+		include_spip('inc/session');
+		$cookie = lire_cookie_session(true);
+		if ($cookie !== 'test_echec_cookie'
+		  && (preg_match(',apache,', \PHP_SAPI) || preg_match(',^Apache.* PHP,', (string) $_SERVER['SERVER_SOFTWARE']))
+		  // Attention dans le cas 'intranet' la proposition de se loger
+		  // par auth_http peut conduire a l'echec.
+		  && !(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']))
+		) {
+			return generer_url_action('cookie', '', false, true);
+		}
 	}
+
+	return '';
 }