# BUG-122 — Déconnexion globale navigable : `GET /sso/logout` **Carte :** fusion #141 (signalement de Bruno, 2026-11-06, capture depuis la console Spark). **Version :** 2.86.0. **Prérequis :** ACC-3.1 (#216) — la déconnexion globale existe déjà dans `POST /api/auth/logout`. ## Constat Le bouton « Déconnexion » du menu compte de la barre commune (dracodev-commons) est une **action relayée à l'hôte** (`cfg.onAction`, sinon événement `draco:bar`) : la barre ne déconnecte jamais elle-même. Or : - console Spark, ObsiGate, Flowdeck, TikTak, ShaarIt et Hub ne branchaient **aucune** action `deconnexion` (clic sans effet, reproduit en navigateur réel sur la console : session draco intacte après le clic) ; - Kanbante, seul branché, ne détruisait que sa session locale — la session SSO survivait ; - et de toute façon, aucun hôte n'aurait pu terminer la session globale : `POST /api/auth/logout` n'est appelable qu'en same-origin depuis l'interface d'ObsiGate. Il manquait le point d'entrée navigable, symétrique de `GET /sso/authorize`. ## Livraison (cette PR, côté émettrice) | Méthode | Chemin | Effet | |---|---|---| | GET | `/sso/logout?return_to=` | Déconnexion globale, puis redirection 302 vers le `return_to` validé (repli « / ») | - La logique de `POST /api/auth/logout` est extraite dans `apply_global_logout(request, response)` (`backend/auth/router.py`) et partagée par les deux entrées : révocation des jetons natifs refresh/access, révocation du `jti` du cookie `draco_session`, effacement des cookies (dont `draco_session` sur le domaine parent). - `return_to` passe par la liste blanche existante (`draco_session.validate_return_to` : https + `dracodev.net` ou sous-domaine) — aucun relais ouvert. - Idempotente : sans session, la route redirige quand même (les hôtes y naviguent même si leur session a déjà expiré). ## Côté hôtes (PR sœurs, carte fusion #141) Chaque hôte branche son action `deconnexion` : destruction de sa session locale d'abord (Flowdeck, TikTak, Kanbante, ShaarIt), puis navigation vers `<émettrice>/sso/logout?return_to=`. La console et le Hub (session draco seule) naviguent directement. Après le parcours complet, « Déconnexion » termine **la session de la suite entière** et la session locale de l'hôte courant. ## Tests `tests/test_draco_session.py` (+3) : révocation du `jti` + redirection vers le `return_to` + cookie effacé (`Max-Age=0`), liste blanche (relais refusé, repli « / »), idempotence sans session.