fix(session): write expires_at in UTC, not local time (audit 6c-2)

CreateSession wrote FormatDateTime(IncHour(Now,24)) = local, but RequireCSRF
and CleanupExpired compare against SQLite datetime('now') = UTC. On negative
UTC offsets the CSRF window fell short of the 24h auth window: between the two,
GETs authed fine but every write got 403 "Invalid CSRF token". Now
IncHour(NowUTC,24) on write + LExpires < NowUTC in Authenticate, so all three
readers are UTC-consistent. Last FormatDateTime(...,Now) in the backend —
closes §2.2 for real. NowUTC + DateUtils already in uses.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-07-20 05:25:37 +01:00
parent 71f45eb8e1
commit c2cc9c72e6
2 changed files with 14 additions and 2 deletions
+7
View File
@@ -615,6 +615,13 @@ sous newKey*. C'est le filet qui aurait attrapé ça.
### 6c-2. 🟠 Expiry de session écrite en local, lue en UTC (corrige §2.2)
> ✅ **RÉSOLU 2026-07-16.** `CreateSession` écrit `IncHour(NowUTC, 24)` et
> `Authenticate` compare `LExpires < NowUTC` ([PM.Session.pas](delphi-backend/Source/PM.Session.pas)).
> Les 3 lecteurs (Authenticate, RequireCSRF, CleanupExpired) sont désormais tous
> sur UTC. `NowUTC` + `System.DateUtils` déjà dans les uses → aucun uses touché.
> §2.2 est maintenant réellement clos (c'était le dernier `FormatDateTime(...,
> Now)` du backend). Sessions existantes : expirent sous 24 h, purgées au boot.
[`CreateSession`](delphi-backend/Source/PM.Session.pas:155) écrit
`FormatDateTime('yyyy-mm-dd hh:nn:ss', IncHour(Now, 24))` — heure **locale**.
C'est le dernier `FormatDateTime(..., Now)` du backend et il contredit la règle