Files
ObsiGate/docs/features/fusion-acc31-sso-draco-session-216.md
T
Spark cb80b08f77
CI / lint (push) Successful in 3m32s
CI / security (push) Successful in 2m18s
CI / test (push) Successful in 5m38s
CI / build (push) Successful in 3m52s
CI / e2e (push) Successful in 19m0s
feat: émettrice SSO draco_session — cookie partagé .dracodev.net, renouvellement et révocation (#216)
2026-10-20 23:33:52 -04:00

3.5 KiB

#216 — Émettrice SSO draco_session (Fusion ACC-3.1)

Statut : ✅ livré le 2026-10-21 (2.71.0)

Contexte

Programme Fusion (accès centralisé ObsiGate / Flowdeck / TikTak / Kanbante), couche 2 — identité. Décision C2 de Bruno (2026-10-20) : cookie de session partagé draco_session sous .dracodev.net (architecture v2.0 §5.2, option 2a). ObsiGate est l'unique émettrice ; les autres applications valideront le jeton localement (ACC-3.2, leurs tickets respectifs) et redirigeront leur connexion vers GET /sso/authorize.

Ce qui est livré

  • backend/draco_session.py — émission et vérification du JWS (HS256, jose) : claims minimaux sub (id utilisateur ObsiGate), name, iat, exp (12 h), jti ; aucun rôle dans le jeton. Rotation : DRACO_SESSION_SECRET_PREV accepté en vérification pendant la fenêtre de bascule.
  • Émission à la connexion : _issue_tokens (auth/router.py) pose le cookie à chaque émission de jetons natifs (mot de passe ou MFA) — attributs Domain=.dracodev.net; Path=/; HttpOnly; Secure (si la requête est en https, via is_secure_cookies); SameSite=Lax.
  • Renouvellement glissant : DracoRenewalMiddleware (ASGI pur, aucun tamponnage des flux SSE/WS) — si la requête porte un cookie d'accès natif valide et que le cookie draco est absent, invalide ou à moins de 2 h de son expiration, un cookie frais est ajouté à la réponse.
  • Déconnexion globale : le logout révoque le jti draco (en plus des jetons natifs) et efface le cookie du domaine parent. Révocations persistées dans data/draco_revoked.json (jti → exp, purge des expirés), exposées aux autres apps par GET /api/sso/revocations protégé par la clé machine DRACO_SSO_MACHINE_KEY (en-tête X-Draco-Machine-Key, 404 si la clé n'est pas configurée) — cache 60 s côté consommatrices.
  • GET /sso/authorize?return_to= : valide le return_to (https + dracodev.net ou sous-domaine, liste blanche stricte anti open-redirect) puis redirige vers la connexion ObsiGate ; après connexion, frontend/js/auth.js repart vers l'application demanderesse (re-validation du domaine côté client).
  • Inerte par défaut : sans DRACO_SESSION_SECRET, aucun cookie n'est émis et le comportement d'ObsiGate est inchangé.

Configuration (déploiement)

Variable Rôle
DRACO_SESSION_SECRET Secret partagé de signature — le même devra être configuré dans Flowdeck et TikTak pour leurs validateurs ACC-3.2. À générer fort (ex. 64 hex) et à ne jamais committer.
DRACO_SESSION_SECRET_PREV Ancien secret pendant une rotation (24 h).
DRACO_SESSION_COOKIE_DOMAIN Domaine du cookie (défaut .dracodev.net ; vide = hôte seul, dev local).
DRACO_SSO_MACHINE_KEY Clé machine de lecture des révocations, à partager avec les apps consommatrices.

⚠️ Déploiement : la fonction ne s'active qu'au redéploiement d'ObsiGate ≥ 2.71.0 avec DRACO_SESSION_SECRET posé dans l'environnement du conteneur. Le SSO complet exige ensuite les validateurs ACC-3.2 (ObsiGate #9, Flowdeck #21, TikTak #213).

Tests

tests/test_draco_session.py — 22 tests : claims minimaux, durée de vie, falsification, expiration, rotation, révocation, fenêtre de renouvellement, liste blanche return_to (8 cas), cookie posé à la connexion (attributs), inactivité sans secret, révocation au logout, renouvellement glissant via middleware, endpoint de révocations (404/401/200).