Compare commits

...
3 Commits
Author SHA1 Message Date
bruno bf030669a0 Merge pull request 'ObsiGate 2.86.3 — retour SSO : réémission du cookie draco garantie à l’arrivée authorize (BUG-125)' (#74) from retour-sso-cookie-draco-bug-125 into main
CI / e2e (push) Blocked by required conditions
CI / lint (push) Successful in 1m22s
CI / security (push) Successful in 24s
CI / test (push) Successful in 3m59s
CI / build (push) Waiting to run
2026-11-08 16:52:00 -05:00
Spark 83a81b931e fix: retour SSO — réémission du cookie draco garantie à l'arrivée authorize (BUG-125)
CI / lint (pull_request) Successful in 1m18s
CI / security (pull_request) Successful in 19s
CI / test (pull_request) Successful in 3m43s
CI / build (pull_request) Successful in 12s
CI / e2e (pull_request) In progress
2026-11-08 21:46:30 +00:00
bruno 23df2bdcbe Merge pull request 'ObsiGate 2.86.2 — entrée SSO : retour honoré à la restauration de session + nom poussé à la barre (BUG-123, BUG-124)' (#73) from entree-sso-bug-123-124 into main
CI / lint (push) Successful in 1m45s
CI / security (push) Successful in 18s
CI / test (push) Failing after 4m52s
CI / build (push) Skipped
CI / e2e (push) Skipped
2026-11-08 13:21:04 -05:00
13 changed files with 170 additions and 14 deletions
+7 -1
View File
@@ -6,7 +6,7 @@ Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/),
et [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
> **En cours de développement** : les changements à venir sont listés dans la section
> [Unreleased](#unreleased). La dernière version livrée est **2.86.2**.
> [Unreleased](#unreleased). La dernière version livrée est **2.86.3**.
---
@@ -14,6 +14,12 @@ et [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
---
## [2.86.3] — 2026-11-08
- **BUG-125 — Aller-retour SSO : le pont de l'application sœur reçoit à nouveau le cookie `draco_session` quand les cookies ont disparu sous une session `sessionStorage` encore « valide »** (suite du chantier « entrée SSO », retest réel de Bruno le 2026-11-08 après le correctif BUG-123 et celui du retour sur le bon hôte) : le retour tombait bien sur l'application demanderesse, mais son pont ne voyait **aucun jeton** et déposait l'utilisateur devant le formulaire, sans message. Chaîne fautive : cookies `access_token` et `draco_session` absents alors que la session semble valide en `sessionStorage` → le chemin court d'`initAuth()` (restauration sans échange serveur, BUG-123) honore le `return_to` immédiatement — le middleware de renouvellement (`DracoRenewalMiddleware`) n'a aucune requête authentifiée à traverser, donc aucune occasion de réémettre le cookie draco manquant. Correctif (`frontend/js/auth.js`) : quand la page est l'arrivée d'un `/sso/authorize` (`return_to` présent), le chemin court est écarté et `initAuth()` passe par le refresh silencieux (cookie refresh, 7 j) suivi de `/api/auth/me` — la réponse traverse le middleware, qui réémet le cookie draco absent ou invalide **avant** que le retour soit honoré ; si le refresh échoue, l'écran de connexion s'affiche comme avant (le `return_to` reste dans l'URL, `saveToken` l'honorera après login frais). Hors arrivée `authorize`, le démarrage est inchangé. Garde : `tests/test_draco_barre.py` (`test_retour_sso_refresh_force_bug_125`) ; variante fautive reproduite puis vérifiée en navigateur réel dans la pile « conteneur dev réel » (requête du pont journalisée : sans cookie draco avant correctif, avec cookie et session ouverte après). Fiche : `docs/features/retour-sso-cookie-draco-bug-125.md`.
---
## [2.86.2] — 2026-11-08
- **BUG-123 — Aller-retour SSO refermé aussi quand la session ObsiGate existe déjà** (chantier « entrée SSO de bout en bout », écart constaté par Bruno en test réel le 2026-11-08) : `GET /sso/authorize?return_to=…` redirige vers `/?return_to=…`, mais le retour n'était honoré que par `AuthManager.saveToken()` (login frais, MFA, WebAuthn). Pour un utilisateur déjà connecté chez ObsiGate, `initAuth()` restaurait la session — jeton encore valide ou refresh silencieux — et affichait l'accueil sans jamais suivre le `return_to` : l'utilisateur restait chez ObsiGate, et l'application sœur ne recevait jamais son pont (aucune session locale). Correctif (`frontend/js/auth.js`) : `_honorReturnTo()` signale désormais la redirection (valeur de retour), et les deux chemins de restauration d'`initAuth()` l'invoquent avant d'afficher l'application. Les refresh silencieux **en cours de session** ne sont pas touchés : ils ne doivent jamais rediriger. Même liste blanche qu'avant (https + `*.dracodev.net`, jamais l'hôte courant). Garde : `tests/test_draco_barre.py` (`test_barre_v070_setuser_et_retour_sso_restauration`) ; chaîne complète prouvée en navigateur réel dans une pile locale aux noms publics (dossier `preuve-entree-sso`). Fiche : `docs/features/entree-sso-bug-123-124.md`.
+3 -3
View File
@@ -4,7 +4,7 @@
**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.
[![Version](https://img.shields.io/badge/Version-2.86.2-blue.svg)]()
[![Version](https://img.shields.io/badge/Version-2.86.3-blue.svg)]()
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Docker](https://img.shields.io/badge/Docker-Ready-blue.svg)](https://www.docker.com/)
[![Python](https://img.shields.io/badge/Python-3.11+-green.svg)](https://www.python.org/)
@@ -977,8 +977,8 @@ Ce projet est sous licence **MIT** — voir le fichier [LICENSE](LICENSE) pour l
## 📝 Changelog
Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.86.2).
Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.86.3).
---
*Projet : ObsiGate | Version : 2.86.2 | Dernière mise à jour : Septembre 2026*
*Projet : ObsiGate | Version : 2.86.3 | Dernière mise à jour : Septembre 2026*
+3 -3
View File
@@ -2,7 +2,7 @@
**Ultra-light web gateway for your Obsidian vaults** — Access, browse, and search all your Obsidian notes from any device via a modern, responsive web interface.
[![Version](https://img.shields.io/badge/Version-2.86.2-blue.svg)]()
[![Version](https://img.shields.io/badge/Version-2.86.3-blue.svg)]()
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Docker](https://img.shields.io/badge/Docker-Ready-blue.svg)](https://www.docker.com/)
[![Python](https://img.shields.io/badge/Python-3.11+-green.svg)](https://www.python.org/)
@@ -1152,8 +1152,8 @@ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE)
## 📝 Changelog
See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.86.2).
See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.86.3).
---
*Project: ObsiGate | Version: 2.86.2 | Last updated: September 2026*
*Project: ObsiGate | Version: 2.86.3 | Last updated: September 2026*
+1 -1
View File
@@ -1 +1 @@
2.86.2
2.86.3
+1 -1
View File
@@ -2626,7 +2626,7 @@ dependencies = [
[[package]]
name = "obsigate-desktop"
version = "2.86.2"
version = "2.86.3"
dependencies = [
"chrono",
"env_logger",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "obsigate-desktop"
version = "2.86.2"
version = "2.86.3"
description = "ObsiGate Desktop — Porte d'entrée native pour vos vaults Obsidian"
authors = ["Bruno Charest"]
edition = "2021"
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://raw.githubusercontent.com/nicedoc/obsigate/main/desktop/tauri.conf.schema.json",
"productName": "ObsiGate",
"version": "2.86.2",
"version": "2.86.3",
"identifier": "com.obsigate.desktop",
"build": {
"frontendDist": "../frontend",
+2
View File
@@ -230,6 +230,7 @@ Avant de corriger quoi que ce soit, un agent IA doit :
| *BUG-122* | Déconnexion du menu compte inerte dans les applications sœurs : la barre commune relaie `deconnexion` à l'hôte, mais la déconnexion globale d'ObsiGate (ACC-3.1) n'est appelable qu'en same-origin (`POST /api/auth/logout`) — aucun point d'entrée navigable pour les autres hôtes | 🟢 corrigé | P1 | ⚙️ backend | IA | `backend/routers/sso.py` (`GET /sso/logout`), `backend/auth/router.py` (`apply_global_logout`) | Depuis la console Spark (ou Flowdeck/TikTak/ShaarIt/Hub) : menu compte → « Déconnexion » → rien ne se passe, la session draco reste vivante (vérifié en navigateur réel : cookie présent, `/api/v1/me` toujours 200) | Nouvelle route `GET /sso/logout?return_to=` : exécute la déconnexion globale (logique partagée `apply_global_logout` : jetons natifs refresh/access révoqués, `jti` draco révoqué, cookie effacé sur le domaine parent) puis redirige vers le `return_to` validé (liste blanche https + *.dracodev.net, repli `/`). Tests `tests/test_draco_session.py` (+3) | Signalé par Bruno le 2026-11-06 (capture console), carte fusion #141 ; les hôtes branchent leur action `deconnexion` sur cette route (PR sœurs). BUG-121 reste réservé au bug de couleur « Secrets » du vault Spark (proposé, non ordonné). Redéploiement Docker requis |
| *BUG-123* | Aller-retour SSO non refermé quand la session ObsiGate existe déjà : `GET /sso/authorize?return_to=…` dépose l'utilisateur sur `/?return_to=…`, mais le retour n'est honoré que par `AuthManager.saveToken()` (login frais, MFA, WebAuthn) — les chemins de restauration de session d'`initAuth()` (jeton encore valide en sessionStorage, ou refresh silencieux au démarrage) affichent l'accueil sans jamais suivre le `return_to` : l'utilisateur reste chez ObsiGate et, revenu manuellement à l'application sœur, n'y a toujours aucune session locale | 🟢 corrigé | P1 | 📱 frontend | IA | `frontend/js/auth.js` (`initAuth`, `_honorReturnTo`) | Navigateur avec session ObsiGate active → Kanbante → « Se connecter avec ObsiGate (SSO) » → retour automatique attendu dans Kanbante, connecté ; constaté en pile locale complète (chaîne d'URL journalisée) : arrivée sur l'accueil ObsiGate, retour jamais suivi | `_honorReturnTo()` retourne si la redirection a eu lieu ; les deux chemins de restauration d'`initAuth()` l'invoquent avant `showApp()` (les refresh en cours de session restent sans redirection). Garde : `tests/test_draco_barre.py` ; preuve navigateur complète du chantier (pile locale aux noms publics) | Signalé par Bruno le 2026-11-08 (test réel, compte « testeur » créé au Hub) ; le sous-cas login frais refermait déjà la boucle (vérifié). Fiche `docs/features/entree-sso-bug-123-124.md`. Redéploiement Docker requis |
| *BUG-124* | Nom du compte absent du menu de la barre commune juste après le login : `renderUserSection()` met à jour le bloc latéral et le drapeau admin de la barre, mais ne pousse jamais le nom — le seul poseur d'identité de la barre est le fetch d'amorçage au `DOMContentLoaded`, limité aux sessions déjà présentes au chargement. Après un login SPA sans rechargement : avatar « ✦ » et en-tête « Compte » jusqu'au rechargement forcé | 🟢 corrigé | P2 | 📱 frontend | IA | `frontend/js/auth.js` (`renderUserSection`), `frontend/index.html`, `frontend/draco-barre.js` (vendange commons v0.7.0) | Se connecter dans la SPA puis ouvrir le menu compte de la barre sans recharger : en-tête « Compte » au lieu du nom (reproduit en pile locale, capture) | Barre commune v0.7.0 re-vendangée verbatim (nouvelle API `DRACO_BAR.setUser`, PR dracodev-commons #15) ; `renderUserSection()` appelle `setUser(name)` / `setUser(null)`, le fetch d'amorçage d'`index.html` pousse aussi le nom par `setUser`. Garde : `tests/test_draco_barre.py` | Signalé par Bruno le 2026-11-08 (captures). Fiche `docs/features/entree-sso-bug-123-124.md`. Redéploiement Docker requis |
| *BUG-125* | Aller-retour SSO : le retour est honoré mais le pont de l'application sœur ne reçoit aucun cookie `draco_session` quand les cookies `access_token` et `draco_session` ont disparu alors que la session semble encore valide en `sessionStorage` — le chemin court d'`initAuth()` (BUG-123) repart sans aucun échange serveur, donc sans la réémission du cookie draco par `DracoRenewalMiddleware` ; côté sœur : jeton absent au pont = redirection vers le formulaire **nu, sans message** (à distinguer de l'échec de résolution, qui affiche le bandeau `draco=echec`, et du rôle « aucun », qui affiche une page 403) | 🟢 corrigé | P1 | 📱 frontend | IA | `frontend/js/auth.js` (`initAuth`) | Pile « conteneur dev réel » : login chez ObsiGate, suppression des cookies `draco_session` + `access_token` (cookie refresh conservé), Kanbante → clic SSO → la requête du pont part **sans cookie draco** (journalisée) → formulaire Kanbante nu ; un second clic, lui, aboutit (le premier passage a provoqué la réémission) | À l'arrivée d'un `/sso/authorize` (`return_to` présent), le chemin court est écarté : `initAuth()` passe par le refresh silencieux + `/api/auth/me`, dont la réponse traverse le middleware de renouvellement qui réémet le cookie draco manquant ou invalide **avant** que le retour soit honoré ; si le refresh échoue, écran de connexion comme avant (le `return_to` reste dans l'URL). Garde : `tests/test_draco_barre.py` (`test_retour_sso_refresh_force_bug_125`) ; preuve navigateur : la variante fautive de la pile retourne connectée après correctif | Signalé par Bruno le 2026-11-08 (retest réel après BUG-123 + retour sur le bon hôte) ; diagnostic complet (formes d'échec du pont cartographiées en pile) dans le dossier `preuve-retour-sso-hote`. Fiche `docs/features/retour-sso-cookie-draco-bug-125.md`. Redéploiement Docker requis |
| # | Titre | Statut | Priorité | Scope | Assigné | Zone (fichier) | Cmd de repro | Correctif / Commit | Notes |
|---|---|---|---|---|---|---|---|---|---|
@@ -366,6 +367,7 @@ Avant de corriger quoi que ce soit, un agent IA doit :
| 2026-10-25 | BUG-120 (suite #223) | Correction | `backend/draco_config.py`, `tests/test_draco_config.py`, `.env.example`, `CHANGELOG.md`, `docs/ISSUES_TODOLIST.md`, `docs/ROADMAP.md`, `docs/features/devprod-urls-config-223.md` | **BUG-120 — le menu inter-apps de la dev pointait la prod** : `window.DRACO_URLS` servait l'agent en `-dev` mais les quatre sœurs en noms officiels, le `.env` dev ne déclarant pas les `DRACO_<APP>_URL`. Correctif dans `draco_config.app_url()` : après l'explicite, **dérivation d'environnement** — hôte de `agent_url()` de la forme `agent<SUFFIXE>.dracodev.net` sans port → sœur en `<slug><SUFFIXE>.dracodev.net` ; hors motif (autre domaine, LAN, IP, port) aucune dérivation ; Gitea jamais dérivée. Vérifié : `test_draco_config.py` 16 passed, suite complète **1668 passed / 9 skipped**, ruff 0 et mypy 0 sur les fichiers touchés (51 erreurs ruff préexistantes ailleurs, inchangées) | 🟢 corrigé (en attente vérif utilisateur) |
| 2026-11-06 | BUG-122 (fusion #141) | Correction | `backend/routers/sso.py`, `backend/auth/router.py`, `tests/test_draco_session.py`, `CHANGELOG.md`, `docs/ISSUES_TODOLIST.md`, `docs/features/deconnexion-globale-bug-122.md`, `VERSION` (+ dérivés) | **BUG-122 — la déconnexion du menu compte ne terminait rien hors ObsiGate** : ajout de `GET /sso/logout`, point d'entrée navigable de la déconnexion globale (logique partagée avec `POST /api/auth/logout`). Vérifié : `test_draco_session.py` 34 passed, ruff 0 et mypy 0 sur les fichiers touchés | 🟢 corrigé (en attente vérif utilisateur) |
| 2026-11-08 | BUG-123 + BUG-124 (chantier entrée SSO) | Correction | `frontend/js/auth.js`, `frontend/index.html`, `frontend/draco-barre.js`, `tests/test_draco_barre.py`, `CHANGELOG.md`, `docs/ISSUES_TODOLIST.md`, `docs/ROADMAP.md`, `docs/features/entree-sso-bug-123-124.md`, `VERSION` (+ dérivés) | **BUG-123 — aller-retour SSO refermé à la restauration de session** : `initAuth()` honore le `return_to` sur ses deux chemins de restauration (jeton valide, refresh silencieux au démarrage), comme le faisait déjà `saveToken` après un login frais. **BUG-124 — nom du compte dans la barre dès le login** : barre commune re-vendangée en v0.7.0 (`DRACO_BAR.setUser`, PR dracodev-commons #15), branchée dans `renderUserSection()` et le fetch d'amorçage. Chaînes prouvées en navigateur réel (pile locale aux noms publics, scénario de Bruno) | 🟢 corrigé (en attente vérif utilisateur) |
| 2026-11-08 | BUG-125 (suite entrée SSO) | Correction | `frontend/js/auth.js`, `tests/test_draco_barre.py`, `CHANGELOG.md`, `docs/ISSUES_TODOLIST.md`, `docs/ROADMAP.md`, `docs/features/retour-sso-cookie-draco-bug-125.md`, `VERSION` (+ dérivés) | **BUG-125 — retour SSO honoré mais pont sans cookie draco** : quand les cookies `access_token` et `draco_session` ont disparu alors que `sessionStorage` croit la session valide, le chemin court d'`initAuth()` repartait sans échange serveur — aucune réémission du cookie draco — et le pont de l'application sœur, sans jeton, déposait l'utilisateur devant son formulaire nu. Correctif : avec `return_to`, `initAuth()` force le refresh silencieux + `/api/auth/me` (réémission par `DracoRenewalMiddleware`) avant d'honorer le retour. Reproduit puis vérifié en navigateur réel dans la pile « conteneur dev réel » (requête du pont journalisée : sans cookie avant, avec cookie après) | 🟢 corrigé (en attente vérif utilisateur) |
---
+2 -1
View File
@@ -1,6 +1,6 @@
# ObsiGate — Roadmap
> **Version :** 2.86.2 | **Dernière mise à jour :** 2026-11-08
> **Version :** 2.86.3 | **Dernière mise à jour :** 2026-11-08
> **Ce fichier ne contient que le travail à venir** (🔵 En cours + ⚪ Backlog) et un index compact
> vers les fonctionnalités livrées.
> - **Méthode de livraison à appliquer pour toute tâche : [DELIVERY_WORKFLOW.md](./DELIVERY_WORKFLOW.md)**
@@ -1229,6 +1229,7 @@
| 225 | Panneau Spark — version du service d'agents visible en mode sidebar (pied du panneau, lue en direct via `GET /healthz`) | 2.79.0 | [features/fusion-panneau-version-agent-225.md](./features/fusion-panneau-version-agent-225.md) |
| BUG-123 | Aller-retour SSO — le `return_to` de `/sso/authorize` est honoré aussi après restauration de session au démarrage (`initAuth`), pas seulement après un login frais | Unreleased | [features/entree-sso-bug-123-124.md](./features/entree-sso-bug-123-124.md) |
| BUG-124 | Barre commune v0.7.0 — `DRACO_BAR.setUser` branché dans `renderUserSection()` : le nom du compte s'affiche dans le menu compte dès le login, sans rechargement | Unreleased | [features/entree-sso-bug-123-124.md](./features/entree-sso-bug-123-124.md) |
| BUG-125 | Aller-retour SSO — à l'arrivée d'un `/sso/authorize`, `initAuth` force le refresh silencieux + `/api/auth/me` pour que le cookie `draco_session` soit réémis avant que le retour soit honoré (pont sœur sans jeton = formulaire nu) | Unreleased | [features/retour-sso-cookie-draco-bug-125.md](./features/retour-sso-cookie-draco-bug-125.md) |
---
@@ -0,0 +1,99 @@
# Retour SSO — cookie draco réémis avant le retour (BUG-125)
Suite du chantier « entrée SSO de bout en bout » : retest réel de
Bruno le 2026-11-08, après la fusion de BUG-123/BUG-124 (2.86.2)
et du correctif « l'hôte de la requête fait foi » côté applications
sœurs (Kanbante 0.46.9). Le retour tombe désormais sur le bon
hôte, mais l'utilisateur arrive devant le formulaire de
l'application sœur, **sans message d'erreur** — pas connecté.
## Diagnostic (pile « conteneur dev réel », navigateur réel)
Les formes d'échec du pont Kanbante ont d'abord été
cartographiées une à une (jetons forgés/révoqués, compte lié
désactivé, rôle « aucun » au registre du Hub) :
| Cause au pont | Arrivée |
|---|---|
| Jeton valide, correspondance saine | session ouverte |
| Échec de résolution (compte lié désactivé) | `/login?draco=echec` **avec bandeau** |
| Rôle « aucun » au registre | page **403 explicite** |
| Jeton absent, illisible (signature) ou **révoqué** | `/login` **nu, sans signal** |
Le formulaire nu de Bruno ne peut donc venir que de la dernière
ligne : au moment du pont, aucun jeton draco valide n'est
présenté. La variante qui le reproduit à l'identique :
1. login chez ObsiGate (session établie, `sessionStorage`
alimenté) ;
2. suppression des cookies `access_token` et `draco_session`
(le cookie `refresh_token`, 7 j, est conservé) ;
3. Kanbante → « Se connecter avec ObsiGate (SSO) » ;
4. la SPA honore le `return_to` par son chemin court
(`sessionStorage` encore « valide ») — **aucun échange
serveur** ;
5. la requête du pont part **sans cookie `draco_session`**
(journalisée) → Kanbante répond `303 /login`, formulaire nu.
Un second clic, lui, aboutit : le premier passage chez ObsiGate
a provoqué entre-temps la réémission du cookie (activité
authentifiée traversant `DracoRenewalMiddleware`).
## Cause racine
La réémission du cookie `draco_session` est opportuniste :
`DracoRenewalMiddleware` ne peut la poser que sur la réponse
d'une requête portant un cookie `access_token` natif valide.
Le chemin court d'`initAuth()` (session « valide » en
`sessionStorage`, ajouté pour BUG-123) redirige vers
l'application sœur **sans aucune requête authentifiée** : si
les deux cookies ont disparu indépendamment de la session
(cookies purgés séparément, profil restauré, domaines nettoyés
à des rythmes différents — le cookie draco vit 12 h,
l'`access_token` 1 h, le refresh 7 j et `sessionStorage`
suit sa propre logique d'onglet), rien ne réémet le cookie
avant le départ, et le pont sœur est muet par construction
(un jeton absent est indiscernable d'un visiteur jamais
connecté).
## Correctif (`frontend/js/auth.js`, `initAuth()`)
Quand la page est l'arrivée d'un `/sso/authorize`
(`return_to` présent dans l'URL), le chemin court est
écarté : `initAuth()` emprunte toujours le chemin du refresh
silencieux — `POST /api/auth/refresh` (rotation, pose un
nouvel `access_token`) puis `GET /api/auth/me`, dont la
requête porte ce cookie et dont la réponse traverse
`DracoRenewalMiddleware` : le cookie draco absent, invalide
ou en fenêtre de renouvellement est réémis **avant**
`_honorReturnTo()`. Si le refresh échoue (plus de session
centrale réelle), l'écran de connexion s'affiche comme
avant et le `return_to`, toujours dans l'URL, sera honoré
par `saveToken` après login frais.
Hors arrivée `authorize`, le démarrage est strictement
inchangé (chemin court conservé pour les visites directes
d'ObsiGate) ; les refresh en cours de session ne redirigent
toujours jamais.
## Garde et preuve
- `tests/test_draco_barre.py::test_retour_sso_refresh_force_bug_125`
(test épinglé : le chemin court est conditionné à l'absence
de `return_to`, et le compte d'appels `_honorReturnTo` de
BUG-123 reste à 2).
- Preuve navigateur dans la pile « conteneur dev réel »
(dossier `preuve-retour-sso-hote`, scripts `diag-*.py`) :
la variante fautive retourne **connectée** après correctif,
la requête du pont portant le cookie draco réémis.
## Périmètre
Ce correctif ferme le mécanisme « retour honoré sans cookie »
côté émettrice. Les deux autres formes silencieuses relevées
au diagnostic relèvent d'autres gestes, inchangés : jeton
révoqué (déconnexion globale, révocation de session au Hub —
guéri par une reconnexion ou une activité chez ObsiGate) et
jeton illisible pour une application sœur (secret partagé
propre à son conteneur — permanent tant que la configuration
n'est pas alignée).
+22 -1
View File
@@ -503,8 +503,29 @@ const AuthManager = {
return true;
}
// BUG-125 : la page est-elle l'arrivée d'un /sso/authorize
// (return_to présent) ? Si oui, le chemin court ci-dessous ne
// doit PAS s'appliquer : il repartait vers l'application
// sœur sans aucun échange serveur, donc sans laisser au
// middleware de renouvellement (DracoRenewalMiddleware)
// l'occasion de réémettre le cookie draco_session. Quand les
// cookies access_token et draco_session ont disparu alors
// que la session semble encore valide en sessionStorage
// (cookies purgés séparément, profil restauré), le pont de
// l'application sœur ne recevait AUCUN cookie : jeton absent
// = formulaire nu, sans message, côté sœur. En forçant le
// refresh silencieux ci-dessous (cookie refresh 7 j) suivi
// de /api/auth/me — dont la requête porte le nouvel
// access_token et dont la réponse traverse le middleware —
// le cookie draco manquant ou invalide est réémis AVANT que
// le retour soit honoré. Si le refresh échoue, l'écran de
// connexion s'affiche comme avant (le return_to reste dans
// l'URL et saveToken l'honorera après login frais).
const retourDemande = new URLSearchParams(
window.location.search).get("return_to");
// Auth enabled — check for existing session
if (this.hasSession() && !this.isTokenExpired()) {
if (this.hasSession() && !this.isTokenExpired() && !retourDemande) {
// BUG-123 : session déjà établie au démarrage (jeton encore
// valide) — si la page a été ouverte par /sso/authorize avec
// un return_to, l'aller-retour SSO doit se refermer ici
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "obsigate",
"version": "2.86.2",
"version": "2.86.3",
"description": "**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.",
"main": "patch.js",
"directories": {
+27
View File
@@ -164,6 +164,33 @@ def test_barre_v070_setuser_et_retour_sso_restauration():
assert "this._honorReturnTo();\n }," in auth_js
def test_retour_sso_refresh_force_bug_125():
# BUG-125 (suite du chantier « entrée SSO », retest réel de
# Bruno le 2026-11-08 après BUG-123) : à l'arrivée d'un
# /sso/authorize (return_to présent), le chemin court
# d'initAuth (« session valide en sessionStorage ») repartait
# sans aucun échange serveur — donc sans réémission du
# cookie draco_session par DracoRenewalMiddleware. Cookies
# access_token et draco_session absents (sessionStorage
# encore « valide ») : le pont de l'application sœur ne
# recevait aucun jeton et déposait l'utilisateur devant son
# formulaire, sans message (reproduit en navigateur réel
# dans la pile « conteneur dev réel », requête du pont
# journalisée sans cookie draco). Garde : le chemin court
# est conditionné à l'ABSENCE de return_to ; avec return_to,
# initAuth passe par le refresh silencieux + /api/auth/me
# (réémission du cookie) avant d'honorer le retour — le
# nombre d'appels _honorReturnTo des chemins de restauration
# reste celui de BUG-123 (2).
auth_js = (FRONTEND / "js" / "auth.js").read_text(encoding="utf-8")
assert 'get("return_to")' in auth_js
assert "&& !retourDemande) {" in auth_js
bloc = auth_js.split("async initAuth()", 1)[1]
assert bloc.index("!retourDemande") < bloc.index(
"await this.refreshAccessToken()")
assert auth_js.count("if (this._honorReturnTo()) return true;") == 2
def test_panneau_spark_integre_218():
# #218 : le bouton Spark de la barre ouvre le panneau de l'agent
# commun (mêmes assets partagés que TikTak / Flowdeck / Kanbante).