2.1 KiB
#217 — Validation locale du jeton draco_session (Fusion ACC-3.2)
Statut : ✅ livré le 2026-10-21 (2.72.0)
Contexte
Suite de l'émettrice SSO (#216, ACC-3.1). Ici, ObsiGate joue son rôle
de consommatrice : get_current_user accepte le cookie partagé
draco_session à défaut de jeton natif valide. C'est la brique qui
servira aussi à l'API de l'agent commun (ACC-4) pour authentifier les
requêtes SSO. Les validateurs des autres applications sont leurs
tickets respectifs (Flowdeck #21, TikTak #213 — TikTak 0.52.0).
Correspondance sub → compte local
ObsiGate est émettrice ET consommatrice : le sub du jeton est
son identifiant d'utilisateur — la résolution est directe, par id,
dans draco_session.user_for_draco() :
- signature/expiration/révocation vérifiées par
verify_token(#216) ; - compte actif exigé ;
- garde-fou BUG-028 appliqué à l'identique : un jeton draco émis
avant le dernier changement de mot de passe (
password_changed_at) est refusé ; - le dict utilisateur retourné porte
_token_vaults(droits du compte),_token_scope = "full"et_draco_sub(traçabilité).
Branchement
Dans backend/auth/middleware.py, chaque sortie « non authentifié »
du chemin natif (aucun jeton, jeton illisible, jti natif révoqué,
compte introuvable/inactif, jeton antérieur au changement de mot de
passe) passe par _draco_fallback(). Sûreté du repli après
déconnexion globale : le logout révoque aussi le jti draco et
efface le cookie (#216), donc un ancien cookie rejoué est refusé par
verify_token.
Limite connue
Le repli authentifie les appels d'API. Le bootstrap d'une session complète du SPA (jetons natifs émis à partir du seul cookie draco) n'est pas couvert : pour ObsiGate, émettrice, la connexion native EST la connexion SSO — le cas d'usage du repli est la continuité d'API quand le jeton natif a expiré avant le cookie partagé, et les consommateurs machine de l'API.
Tests
tests/test_draco_session.py (+4) : /api/auth/me avec le seul
cookie draco (200, bon utilisateur), jti révoqué refusé, sub inconnu
refusé, inactivité sans secret configuré.