Sécurise le cookie de session par signature HMAC
Le cookie user_id était lu tel quel depuis la requête, ce qui permettait à
n'importe qui de forger `user_id=victime` dans DevTools/curl et d'accéder à
toutes les routes "authentifiées" (lecture/écriture des pointages, export,
régénération des tokens Tasker, etc.). Le mot de passe bcrypt ne servait
donc à rien.
Le cookie est maintenant au format `<user_id>.<hmac_sha256_hex>` signé avec
une clé persistée dans /data/secret.key (auto-générée, stable entre
redémarrages). La vérification utilise hmac.compare_digest pour éviter les
fuites par timing. Toutes les routes appellent _get_user qui valide la
signature à chaque requête.
Les tests de test_logs.py récupèrent désormais le cookie réellement signé
par le serveur, et un nouveau module test_security.py couvre le rejet des
cookies forgés/tamponnés/rejoués.
Le DATA_DIR temporaire des tests est centralisé dans conftest.py pour éviter
les collisions entre modules de test.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@ -69,6 +69,24 @@ def save_config(cfg: dict):
|
||||
CONFIG_FILE.write_text(json.dumps(cfg, indent=2, ensure_ascii=False))
|
||||
|
||||
|
||||
def load_or_create_secret() -> bytes:
|
||||
"""Charge ou crée la clé secrète utilisée pour signer les cookies de session.
|
||||
|
||||
Persistée hors config pour ne pas être réinitialisée à chaque modification des
|
||||
réglages et rester stable entre les redémarrages.
|
||||
"""
|
||||
secret_file = DATA_DIR / "secret.key"
|
||||
secret_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
if secret_file.exists():
|
||||
try:
|
||||
return bytes.fromhex(secret_file.read_text().strip())
|
||||
except ValueError:
|
||||
pass
|
||||
secret = secrets.token_bytes(32)
|
||||
secret_file.write_text(secret.hex())
|
||||
return secret
|
||||
|
||||
|
||||
def heures_jour_min() -> int:
|
||||
return int(float(load_config().get("heures_jour", 7.8)) * 60)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user