Déconnexion OpenID Connect par canal dérobé
Sur cette page
Avec la connexion unique, un utilisateur ouvre plusieurs applications avec une seule authentification TOSIAM. Mais chaque application garde aussi sa propre session : quand il se déconnecte de l’une, les autres le croient toujours connecté.
La déconnexion par canal dérobé (OpenID Connect Back-Channel Logout) règle ce problème. Quand la session TOSIAM se termine, TOSIAM envoie directement, de serveur à serveur, un jeton de déconnexion (logout token) signé à chaque application où l’utilisateur s’était connecté. Chacune vérifie le jeton et ferme la session locale de cet utilisateur.
Navigateur ── se déconnecter ──▶ RPA ──▶ TOSIAM /connect/endSession
│ fin de la session TOSIAM
├── POST logout_token ──▶ RPA /backchannel_logout
└── POST logout_token ──▶ RPB /backchannel_logout ─▶ session RPB ferméeLe code est dans le dépôt tosiam-samples, dossier oidc_backchannel_logout : une application Node.js (rp), lancée deux fois sous les noms RPA (port 9001) et RPB (port 9005), et une petite API protégée (protected, port 9002).
Étape 1 : le fournisseur#
Dans le royaume ref, le service OAuth2 Provider (voir Fournisseur OAuth2) a deux réglages pour cette fonction :
- Prendre en charge la déconnexion par canal dérobé (
backChannelLogoutSupported) : à activer. Le document de découverte annonce alors"backchannel_logout_supported": true. - Transmettre une revendication sid dans le jeton de déconnexion (
backChannelLogoutSessionSupported) : laissez-le désactivé, voir l’encadré ci-dessous.
Activez aussi Autoriser les clients à passer outre le consentement, comme dans le tutoriel Angular, pour ne pas demander de consentement.
Étape 2 : les clients#
Créez deux clients rpa et rpb, de type Confidentiel : ces applications tournent sur un serveur et gardent un secret. Pour rpa :
| Réglage | Valeur |
|---|---|
| URI de redirection | http://localhost:9001/callback |
| Scope(s) | openid, profile |
| Méthode d’authentification au point d’accès des jetons | client_secret_basic |
| Paramètre Code verifier requis (PKCE) | activé |
| Consentement implicite | activé |
| URI de redirection après déconnexion (onglet OpenID Connect) | http://localhost:9001/loggedout |
| Algorithme de signature du jeton d’identité | RS256 |
| URI de déconnexion par canal dérobé (onglet OpenID Connect) | http://localhost:9001/backchannel_logout |
| Identifiant de session requis à la déconnexion par canal dérobé | désactivé |
rpb a les mêmes réglages avec le port 9005.
L’algorithme RS256 compte double : TOSIAM signe le jeton de déconnexion avec l’algorithme du jeton d’identité du client. Avec la valeur par défaut HS256, le jeton serait signé avec le secret du client au lieu de la clé publiée par le fournisseur.
Étape 3 : recevoir le jeton de déconnexion#
Chaque application expose POST /backchannel_logout. TOSIAM y envoie un formulaire application/x-www-form-urlencoded avec un seul champ, logout_token, un JWT signé.
L’application doit vérifier ce jeton avant d’agir. La spécification impose de contrôler la signature, l’émetteur, l’audience, la présence de l’événement de déconnexion et l’absence de nonce. L’exemple utilise la bibliothèque jose et les clés publiques du fournisseur (jwks_uri du document de découverte) :
const { payload } = await jwtVerify(logoutToken, jwks, {
issuer: ISSUER, // http://localhost:8080/tosiam/oauth2/ref
audience: CLIENT_ID, // rpa ou rpb
algorithms: ['RS256'],
maxTokenAge: '2 minutes',
requiredClaims: ['iat', 'exp', 'jti'],
});
const event = payload.events?.[BACKCHANNEL_EVENT]; // http://schemas.openid.net/event/backchannel-logout
if (!(event === '{}' || (event && typeof event === 'object'))) throw new Error('événement absent');
if ('nonce' in payload) throw new Error('nonce interdit dans un jeton de déconnexion');
if (!payload.sub && !payload.sid) throw new Error('ni sub ni sid');
if (seenJti.has(payload.jti)) throw new Error('jti déjà reçu (rejeu)');Le jeton reçu est accepté une seule fois (jti mémorisé jusqu’à son expiration). La valeur de l’événement est normalement l’objet vide {} ; TOSIAM envoie aujourd’hui la chaîne "{}", que l’exemple accepte aussi.
Il faut ensuite retrouver les sessions de l’utilisateur. L’application tient, à la connexion, un index sub → sessions ; à la réception du jeton, elle ferme toutes les sessions de ce sub et répond 200 :
const ids = [...(sessionsBySub.get(claims.sub) ?? [])];
for (const id of ids) {
await destroySession(id); // session express-session de l'utilisateur
}
res.set('Cache-Control', 'no-store');
res.sendStatus(200);Un jeton invalide reçoit 400 : TOSIAM le journalise, sans réessayer.
Étape 4 : lancer et tester#
Dans trois terminaux :
cd tosiam-samples/oidc_backchannel_logout/rp && npm install && npm run rpa # http://localhost:9001
cd tosiam-samples/oidc_backchannel_logout/rp && npm run rpb # http://localhost:9005
cd tosiam-samples/oidc_backchannel_logout/protected && npm install && npm startOuvrez http://localhost:9001, cliquez sur Se connecter et authentifiez-vous dans TOSIAM. Appeler l’API vérifie que le jeton d’accès est accepté.
Ouvrez ensuite http://localhost:9005 et cliquez sur Se connecter : RPB obtient sa session sans redemander le mot de passe, grâce à la session TOSIAM.
Revenez sur RPA et cliquez sur Se déconnecter. RPA ferme sa session, puis redirige le navigateur vers le point de fin de session de TOSIAM (/connect/endSession, avec id_token_hint). TOSIAM ferme sa propre session et envoie un jeton de déconnexion à RPA et à RPB. Rafraîchissez RPB : l’utilisateur n’y est plus connecté, et la page indique l’avis reçu.
Ce que TOSIAM envoie#
Contenu d’un jeton de déconnexion reçu par RPB (signé RS256, en-tête avec le kid de la clé du fournisseur) :
| Revendication | Valeur |
|---|---|
iss | http://localhost:8080/tosiam/oauth2/ref |
aud | identifiant du client (rpb) |
sub | identifiant de l’utilisateur (dduck) |
iat, exp | émission et expiration (durée de vie des jetons d’identité du client) |
jti | identifiant unique du jeton |
events | {"http://schemas.openid.net/event/backchannel-logout": "{}"} |
TOSIAM n’avertit que les applications où l’utilisateur s’est connecté pendant cette session : il les enregistre dans la session au moment de chaque autorisation. Les envois se font l’un après l’autre, pendant la requête de déconnexion ; une réponse 200 ou 204 est attendue. Les échecs sont journalisés (journal amSession) et chaque envoi produit l’événement d’audit AM-BACK-CHANNEL-LOGOUT.
Quand TOSIAM envoie-t-il les jetons ?#
| Fin de la session TOSIAM | Jetons envoyés |
|---|---|
Déconnexion demandée par une application (/connect/endSession) | Oui |
| Déconnexion depuis les pages de TOSIAM (XUI) | Oui |
| Suppression de la session par un administrateur (console, page Sessions) | Non : dans la version actuelle, la suppression échoue pour ces sessions |
| Expiration de la session (inactivité, durée maximale) | Non |
| Sessions sans état (stateless) | Non pris en charge |
Comme l’expiration n’est pas signalée, donnez aux sessions des applications une durée de vie au plus égale à celle des sessions TOSIAM.
En cas de problème#
| Symptôme | Cause probable |
|---|---|
| RPB reste connecté après la déconnexion de RPA | URI de déconnexion par canal dérobé absente du client rpb, ou fournisseur sans Prendre en charge la déconnexion par canal dérobé ; RPB s’était connecté avant l’activation |
L’application refuse le jeton (400, algorithme ou signature) | Client en HS256 : passez l’algorithme de signature du jeton d’identité en RS256 |
L’application répond 400 « jti déjà reçu » | Même jeton reçu deux fois (rejeu) : comportement attendu |
| Rien n’est reçu alors que TOSIAM est configuré | L’application n’est pas joignable depuis le serveur TOSIAM (pare-feu, localhost d’une autre machine) ; voir le journal amSession |
Deux applications sur localhost se déconnectent l’une l’autre | Elles partagent le même nom de cookie de session : les cookies ne distinguent pas les ports |
Pour aller plus loin#
- Application Angular avec OpenID Connect : client public, PKCE, déconnexion par le point de fin de session.
- Enregistrer un client : tous les réglages d’un client OAuth2.
- Sessions : durée de vie et suppression des sessions TOSIAM.
- Spécification : OpenID Connect Back-Channel Logout 1.0.
Mis à jour le