SSO dans les applications embarquées
Comment offrir une authentification unique fluide lorsque votre application est intégrée à l'intérieur d'une autre application connectée à Trousseau.
Le problème
Lorsque deux applications connectées à Trousseau sont intégrées ensemble: par exemple, TriggerFlow s'exécutant comme un onglet à l'intérieur de Thaïs PMS: l'utilisateur attend une expérience d'authentification unique. Il doit se connecter une fois, et la seconde application doit s'authentifier automatiquement.
Cela fonctionne par défaut dans la plupart des cas, mais les fonctionnalités de confidentialité des navigateurs modernes (blocage des cookies tiers, Safari ITP, Privacy Sandbox de Chrome) peuvent briser ce flux si le pattern d'embedding n'est pas choisi avec soin.
Ce guide couvre les trois patterns d'embedding courants, les pièges navigateur de chacun, et quand utiliser le flux OAuth 2.0 Token Exchange pour les scénarios avancés.
Comment le SSO fonctionne entre deux applications Trousseau
Les deux applications sont enregistrées comme des clients OIDC distincts de Trousseau. Lorsqu'un utilisateur s'authentifie sur la première application :
- Le navigateur effectue le flux authorization code OIDC sur
auth.trousseau.app - Trousseau dépose un cookie de session sur le domaine
auth.trousseau.app - L'utilisateur est redirigé vers l'app A avec un code d'autorisation
Quand l'utilisateur accède ensuite à l'app B (embarquée ou non) :
- L'app B démarre son propre flux OIDC → redirection vers
auth.trousseau.app - Trousseau voit le cookie de session existant → aucune demande de mot de passe
- Trousseau redirige immédiatement vers l'app B avec un code d'autorisation
L'utilisateur voit un bref flash de redirections (< 1 seconde), pas d'écran de connexion.
La question critique est de savoir si le navigateur donne accès à ce cookie de session quand le flux OIDC de l'app B démarre. Cela dépend du mode d'embedding de l'app B.
Pattern 1: Nouvel onglet ou fenêtre (recommandé)
L'application parent ouvre l'application enfant dans un nouvel onglet ou une nouvelle fenêtre (typiquement via <a target="_blank"> ou window.open()).
┌─────────────────┐ ┌─────────────────┐
│ Thaïs PMS │ │ TriggerFlow │
│ (connecté) │ clic │ (nouvel onglet)│
│ │ ────────▶│ │
│ [Bouton onglet │ │ → Flux OIDC │
│ TF] │ │ │
└─────────────────┘ └─────────────────┘Comportement navigateur : la redirection OIDC devient une navigation top-level dans le nouvel onglet. Les cookies sur auth.trousseau.app sont traités comme first-party pendant cette navigation. La session SSO est lue sans aucune restriction de cookie tiers.
C'est le pattern le plus robuste. Il fonctionne dans tous les navigateurs, avec tous les réglages de confidentialité, et ne nécessite aucun code particulier au-delà d'une intégration OIDC standard.
Recommandé pour : toute intégration où les deux applications n'ont pas besoin de partager le même cadre navigateur.
Pattern 2: Embedding en iframe (pièges navigateur)
L'application enfant est intégrée dans l'application parent via un <iframe> :
<!-- Dans Thaïs PMS -->
<iframe src="https://app.trigger-flow.com/embed" ...></iframe>Quand TriggerFlow dans l'iframe redirige vers auth.trousseau.app pour OIDC, deux problèmes peuvent survenir.
Problème 1: Blocage des cookies tiers
Le navigateur peut refuser d'envoyer le cookie de session Trousseau car, du point de vue de l'iframe, auth.trousseau.app est un domaine tiers. L'utilisateur se retrouve sur la page de login Trousseau, le SSO est cassé.
Navigateurs concernés (en 2026) :
- Safari (ITP): bloque tous les cookies tiers par défaut
- Firefox (ETP strict): bloque la plupart des cookies tiers
- Chrome: retrait progressif des cookies tiers via Privacy Sandbox
Problème 2: La redirection casse le contexte iframe
Si l'iframe fait une redirection top-level (top.location = ...) pour effectuer OIDC, l'utilisateur quitte complètement l'application parent. Quand il revient, il n'est plus dans l'iframe.
Mitigations
| Mitigation | Principe | Support |
|---|---|---|
| Storage Access API | L'iframe appelle document.requestStorageAccess() avant le flux OIDC. L'utilisateur voit une invite accordant l'accès aux cookies de auth.trousseau.app. | Safari, Firefox, Chrome: mais nécessite une interaction utilisateur et reste imparfait |
| FedCM | API native de fédération d'identité. Trousseau expose une config FedCM ; le navigateur gère la lookup de session sans cookies. | Chrome (en rollout), Edge partiel, Safari/Firefox pas encore |
| Popup top-level | L'iframe ouvre une fenêtre popup pour le flux OIDC (window.open). La popup s'exécute en top-level et renvoie via postMessage. | Universel, mais ajoute une popup visible |
| OAuth 2.0 Token Exchange | L'application parent obtient un token pour l'audience de l'app enfant au nom de l'utilisateur. Aucune auth au niveau de l'iframe. Voir Pattern 4 ci-dessous. | Universel, mais nécessite une configuration de confiance parent-enfant |
Évitez l'authentification silencieuse dans les iframes (prompt=none) comme stratégie principale. Elle repose sur les cookies tiers et cassera à mesure que les navigateurs durcissent les contrôles de confidentialité. Utilisez-la uniquement comme fast path d'amélioration progressive, avec l'une des mitigations ci-dessus en fallback.
Recommandé pour : les cas où l'iframe est non négociable. Prévoir le travail de mitigation dès le départ.
Pattern 3: Reverse-proxy (même origine)
L'application enfant est servie sous un chemin du domaine de l'application parent :
https://app.monhotel.com/ → Thaïs PMS
https://app.monhotel.com/triggerflow → TriggerFlow (reverse-proxifié)Du point de vue du navigateur, les deux applications sont same-origin. Cookies, storage, et la session SSO sont tous first-party.
Comportement navigateur : identique au Pattern 1: aucun problème de tiers, aucune mitigation nécessaire.
Contrepartie : nécessite une coordination d'infrastructure. L'app parent exécute un reverse-proxy (nginx, Caddy, Traefik) qui transfère /triggerflow/* vers l'origine de l'app enfant, réécrivant les headers et les chemins au besoin.
Recommandé pour : les déploiements white-label ou les partenariats étroitement couplés où les deux apps sont opérées par la même équipe ou sous une marque unique visible par le client.
Pattern 4: OAuth 2.0 Token Exchange (avancé)
Quand le pattern iframe est inévitable et que les mitigations navigateur ne conviennent pas, le RFC 8693 Token Exchange permet à l'app parent d'obtenir un token pour l'app enfant au nom de l'utilisateur: sans aucun flux OIDC à l'intérieur de l'iframe.
Flux
Backend Thaïs Trousseau TriggerFlow
│ │ │
│ 1. Login utilisateur Thaïs │ │
│ (OIDC standard) │ │
│ │ │
│ 2. Clic onglet TF │ │
│ │ │
│ 3. POST /token │
│ grant_type=token-exchange │ │
│ subject_token={thais_at} │ │
│ audience=triggerflow │ │
│ ────────────────────────────▶│ │
│ │ │
│ 4. Access token TF │ │
│ ◀────────────────────────────│ │
│ │
│ 5. Transmission du token TF via postMessage (ou URL) │
│ ──────────────────────────────────────────────────────────▶│
│ │
│ │ 6. Validation du token │
│ │◀───────────────────────────│
│ │
│ │ Session établie │
│ │Exemple de requête
POST https://auth.trousseau.app/application/o/token/
Content-Type: application/x-www-form-urlencoded
Authorization: Basic {base64(thais_client_id:thais_client_secret)}
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token={access_token_utilisateur_depuis_thais}
&subject_token_type=urn:ietf:params:oauth:token-type:access_token
&audience=triggerflow-oidc
&scope=openid email profileModèle de confiance
Token Exchange requiert une configuration de confiance explicite dans Trousseau :
- Le client parent (Thaïs) doit être autorisé à demander des tokens pour l'audience enfant (TriggerFlow)
- L'équipe KeySuite configure ceci dans Authentik lors de l'onboarding partenaire
- L'app enfant doit accepter les tokens Token Exchange (vérifier le claim
aud, pas l'émetteur)
Token Exchange accorde à une application la capacité d'agir au nom des utilisateurs dans une autre application. N'activez-le qu'entre partenaires qui entretiennent déjà une relation de confiance (par exemple Thaïs intégrant TriggerFlow dans le cadre d'un partenariat commercial). Contactez l'équipe KeySuite avant de vous appuyer sur ce flux.
Recommandé pour : les partenariats d'embedding étroit (comme Thaïs ↔ TriggerFlow) où le SSO iframe doit fonctionner universellement sans mitigations spécifiques au navigateur.
Matrice de décision
| Embedding | Problèmes navigateur | Effort dev | Recommandation |
|---|---|---|---|
| Nouvel onglet/fenêtre | Aucun | Faible | ✅ Choix par défaut |
| Iframe (domaine tiers) | Blocage cookies Safari/Firefox/Chrome | Moyen (mitigations nécessaires) | ⚠️ À éviter si possible |
| Iframe + reverse-proxy | Aucun (même origine) | Élevé (coordination infra) | ✅ Scénarios white-label |
| Iframe + Token Exchange | Aucun | Élevé (configuration confiance + RFC 8693) | ✅ Partenariats étroits |
Checklist de tests
Avant de livrer une intégration SSO embarquée, validez dans tous les navigateurs cibles :
- Safari 17+ avec ITP activé (par défaut)
- Firefox 120+ avec ETP réglé sur « Strict »
- Chrome 125+ avec cookies tiers bloqués (simule la fin de Privacy Sandbox)
- Edge 125+ avec prévention du pistage « Strict »
- Test avec un profil navigateur vierge (pas de session Trousseau préalable)
- Test avec une session Trousseau active (hot path SSO)
- Test d'expiration de session à l'intérieur de l'app embarquée