Single Sign-On

Chaque application Inklura — la console, SMS Designer, SEO, Mail, POS, support — partage une connexion unique. Le SSO fonctionne grâce à deux mécanismes coopérants :

  1. OIDC PKCE — chaque application authentifie les utilisateurs contre le fournisseur d'identité partagé, et la session propre à l'IdP rend les connexions suivantes silencieuses.
  2. Un token de transfert console→app — pour lancer silencieusement un utilisateur de la console déjà authentifié dans une application sœur (utilisé lors de l'embarquement).

Pour la vue d'ensemble de l'authentification (cookies de session, JWT Bearer, magic links), voir Authentification.

Mécanisme 1 — OIDC PKCE par application

Le fournisseur d'identité est auth.1clic.pro. Chaque application *.inklura.fr est son propre client OIDC PKCE (S256) public — un client public sans client secret :

  • par ex. client id smsdesigner-prism, redirect https://smsdesigner.inklura.fr/auth/callback
  • ou le client de realm partagé inklura-admin, utilisé par seo + pos

Scopes : openid profile email offline_access.

Cookies de session de portée hôte

Après l'aller-retour OIDC, chaque application génère son propre cookie de session de portée hôte :

Set-Cookie: <session>; Path=/; SameSite=Lax; Secure

Notez qu'il n'y a aucun attribut Domain= — le cookie est cloisonné à cet unique hôte, pas partagé entre sous-domaines.

Pourquoi la connexion reste silencieuse entre sous-domaines

Les utilisateurs semblent « connectés partout », mais pas parce qu'un cookie est partagé. Chaque application a son propre cookie de portée hôte. Ce qui est partagé, c'est la session propre à l'IdP sur auth.1clic.pro : quand un utilisateur déjà authentifié visite une seconde application, l'aller-retour PKCE de cette application se termine silencieusement au niveau de l'IdP (aucune ressaisie de mot de passe), et l'application génère son cookie local.

app B : pas de cookie local ──> redirection vers auth.1clic.pro
        l'IdP a déjà une session ──> autorisation silencieuse ──> /auth/callback
        app B génère son PROPRE cookie de portée hôte
Info

Précision sur node:crypto. L'isolat V8 de PRISM propose des stubs pour node:crypto et crypto.subtle.digest, de sorte que SHA-256 / HMAC sont implémentés à la main en pur JS dans le oidc.ts de chaque application. Par défaut, l'id_token est décodé, pas vérifié cryptographiquement — l'ancre de confiance est l'échange de token protégé par TLS avec l'IdP. Une vérification RS256 via JWKS optionnelle est disponible derrière un flag.

Mécanisme 2 — token de transfert console→app

Pour déposer silencieusement un utilisateur de la console déjà authentifié dans une application sœur (par exemple à l'intérieur d'un iframe), la console génère un token signé à courte durée et redirige le navigateur vers l'application cible, qui le vérifie et génère sa propre session locale.

Format du token

b64url(JSON(payload)) + "." + b64url(hmacSha256(INKLURA_SSO_SECRET, b64payload))
  • Le HMAC est calculé sur le payload encodé en b64url en utilisant INKLURA_SSO_SECRET.
  • TTL : 120 secondes.

Payload :

{ "sub": "…", "email": "…", "name": "…", "tenant_id": "…", "aud": "…", "iat": 0, "exp": 0 }

Le claim aud est le client id OIDC de l'application cible. Parce que la signature couvre aud, le token n'est pas rejouable sur une autre application — un token généré pour l'application A échoue à la vérification d'audience de l'application B.

La route de génération

GET /api/manage/designer-sso?app=<key>&next=<path>&embed=1
  • Protégée par le contrôle d'accès propre à la console.
  • Ne porte que l'identité de l'appelant lui-même (il ne peut pas se faire passer pour un autre utilisateur).
  • Résout l'application sœur sur le même domaine enregistrable et redirige en 302 vers celle-ci avec le token.

La route d'atterrissage (côté application)

L'application cible expose une route d'atterrissage qui consomme le token :

Route d'atterrissage Applications
/auth/sso mail, sms, ads
/auth/manage-sso seo, pos, support

La route d'atterrissage :

  1. Vérifie le HMAC.
  2. Contrôle exp (non expiré).
  3. Affirme aud === CLIENT_ID (cette application est bien l'audience visée).
  4. Génère la session locale et redirige vers next.
console (authentifiée) ──GET /api/manage/designer-sso?app=mail&next=/inbox&embed=1
   génère le token (aud = client id de mail, TTL 120s)
   302 ──> https://mail.inklura.fr/auth/sso?token=…&next=/inbox
      vérifie HMAC + exp + aud === CLIENT_ID
      génère la session locale ──> 302 /inbox

Même site vs nouvel onglet

Quand la console lance une application sœur de cette façon, les applications du même site sont embarquées dans un iframe ; les applications d'un site différent sont lancées dans un nouvel onglet. Les règles de framing qui rendent possible l'embarquement même-site sont couvertes dans Embarquement en iframe.

Voir aussi