diff --git a/Framework/Csrf.php b/Framework/Csrf.php
index 584b1c9d..a3ee6f8e 100755
--- a/Framework/Csrf.php
+++ b/Framework/Csrf.php
@@ -1,28 +1,45 @@
bin2hex(random_bytes(32)),
+ 'created_at' => time(),
+ ];
}
- return $_SESSION['csrf_token'];
+ return $_SESSION['csrf_token']['value'];
+ }
+
+ /**
+ * Vérifie si le token a expiré
+ */
+ private static function isExpired(): bool {
+ $createdAt = $_SESSION['csrf_token']['created_at'] ?? 0;
+ return (time() - $createdAt) > self::EXPIRATION;
}
/**
* Valide le token soumis
*/
public static function validateToken(string $submittedToken): bool {
- $sessionToken = $_SESSION['csrf_token'] ?? '';
+ // Rejeté si la session ne contient pas de token
+ if (empty($_SESSION['csrf_token'])) return false;
- if (empty($sessionToken)) return false;
+ // Rejeté si expiré
+ if (self::isExpired()) {
+ self::regenerate();
+ return false;
+ }
- // ✅ hash_equals évite les attaques par timing
- return hash_equals($sessionToken, $submittedToken);
-
- // ⚠️ On NE supprime PAS le token ici (réutilisable)
+ // Comparaison sécurisée (résistante aux attaques par timing)
+ return hash_equals($_SESSION['csrf_token']['value'], $submittedToken);
}
/**
@@ -30,14 +47,17 @@ class Csrf
*/
public static function field(): string {
$token = self::generateToken();
- return '';
+ return '';
}
/**
- * Régénère le token (à appeler à la déconnexion)
+ * Régénère le token (déconnexion, ou expiration)
*/
public static function regenerate(): void {
- $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
+ $_SESSION['csrf_token'] = [
+ 'value' => bin2hex(random_bytes(32)),
+ 'created_at' => time(),
+ ];
}
-
}
\ No newline at end of file