Suggérer des modifications

Introduction

Le standard OpenID Connect (OIDC) propose un mécanisme de gestion de session permettant aux fournisseurs d’identité (OpenID Provider - OP) et aux applications clientes (Relying Parties - RP) de gérer la déconnexion des utilisateurs de manière cohérente et sécurisée.

Ce mécanisme repose sur deux services principaux au niveau de l’OP :

  • La déconnexion de l’utilisateur (Logout)
  • L’avertissement des applications connectées de cette déconnexion

Gestion du Logout avec TOSIAM

TOSIAM offre plusieurs solutions pour gérer la déconnexion d’un utilisateur dans le cadre d’OIDC :

  1. API /connect/endSession?id_token_hint=<ID_TOKEN> permet de supprimer la session utilisateur et de le déconnecter de son application. Cependant, elle ne déclenche pas de Single Logout (SLO) et ne déconnecte pas automatiquement toutes les applications associées à cet utilisateur.
  2. API /token/revoke permet d’invalider un access token ou un refresh token. Toutefois, elle ne supprime pas la session utilisateur et ne déclenche pas non plus de SLO.

Gestion du Single Logout (SLO) avec TOSIAM

TOSIAM supporte le mécanisme de déconnexion standardisé par OIDC, qui permet à un utilisateur de se déconnecter de toutes les applications connectées à l’OP.

Front Channel Logout

L’avertissement de la déconnexion aux différents RP se fait avec le Front Channel Logout via check_session_iframe , postMessage est utilisé pour que l’Iframe RP demande à l’Iframe OP si la session a été modifiée, Si la session a été supprimé, le code de l’Iframe RP provoque une déconnexion locale. OpenID Connect Session Management 1.0,

Le Back-Channel Logout

Le mécanisme défini par la spécification OpenID Connect Back-Channel Logout 1.0 qui permet à l’OP d’informer les applications clientes RP de la fin d’une session utilisateur. Contrairement au Front-Channel Logout, qui repose sur des redirections et des interactions côté navigateur, le Back-Channel Logout fonctionne entièrement côté serveur, garantissant une plus grande fiabilité et confidentialité.

Lorsqu’un utilisateur se déconnecte ou que sa session expire, le fournisseur d’identité envoie un jeton de déconnexion (logout token) aux applications clientes concernées. Ces applications doivent disposer d’une URL de déconnexion back-channel, configurée dans leur profil client, capable de recevoir et de traiter ce jeton.

Le fournisseur d’identité maintient une liste des clients connectés à la session et, lorsqu’elle devient invalide, il contacte chacune des applications pour leur notifier la déconnexion de l’utilisateur.

Chaque Relying Party doit alors :

  • Valider le jeton de déconnexion (authenticité et validité).
  • Détruire l’état de session associé à l’utilisateur.
  • Répondre au fournisseur d’identité avec le statut de la déconnexion.

Principales différences entre Front channel logout et Backen channel logout

Front-Channel Logout

Les RP ne sont pas directement avertis par le serveur de l’OP, mais doivent écouter une redirection, charger un iframe ou exécuter du JavaScript côté client pour détecter la déconnexion. Si l’utilisateur ferme le navigateur trop tôt ou bloque les scripts, certains RP peuvent ne pas être informés.

Back-Channel Logout

L’OP envoie activement une requête HTTP POST aux RP enregistrés, avec un Logout Token contenant le sid (Session ID / optionnel) et sub (user ID). Chaque RP peut valider le token et supprimer la session côté serveur sans dépendre du navigateur ou de l’utilisateur.

Le Back-Channel Logout est prévu pour les RP confidentiels

La norme OpenID Connect Back-Channel Logout 1.0 ne mentionne pas explicitement les RP publics. Cependant, plusieurs éléments indiquent que le protocole est conçu principalement pour les RP confidentiels, et que les RP publics posent des défis techniques majeurs.

  • Enregistrement de l’URI de logout back-channel Un RP public (ex. app mobile, client JS) ne peut pas exposer une URI fixe et accessible sur Internet, contrairement à un serveur backend.

  • Contraintes réseau pour un RP public Une application mobile ou un client JavaScript ne possède pas de serveur fixe accessible par l’OP. Ces applications tournent derrière des firewalls, NAT et réseaux locaux, rendant le back-channel logout inopérant.

  • Exigences sur la validation du Logout Token Les RP publics n’ont pas de secret client et ne peuvent pas valider un JWT signé, ce qui rend difficile la sécurisation du processus.

BackChannel Logout avec TOSIAM

TOSIAM supporte le Back-Channel Logout en tant qu’OP, ne supporte que les server-side sessions. Lorsque BackChannel logout est activée, TOSIAM envoie un jeton de déconnexion à une URL spécifique configurée dans le profil client du relying party. Cette URL doit être valide et pointer vers une page ou une application capable de traiter ce jeton.

TOSIAM conserve dans la session utilisateur la liste des clients (RPs) connectés. Lorsque la session devient invalide (déconnexion volontaire ou expiration), TOSIAM parcourt cette liste et envoie le logout token à chaque URL enregistrée.

Ce mécanisme permet à l’OP d’informer tous les RPs ayant utilisé cette session pour générer des tokens d’accès, afin qu’ils puissent déconnecter l’utilisateur côté application.

Processus de déconnexion Session utilisateur devient invalide, TOSIAM envoie un jeton de déconnexion aux relying parties concernées. Le relying party vérifie le jeton et supprime toute donnée associée à la session (ID de session, utilisateur, émetteur). Le relying party envoie un retour à TOSIAM avec le résultat de la déconnexion, conformément au standard décrit dans la spécification OIDC Back-Channel Logout. TOSIAM enregistre un événement d’audit de type AM-BACK-CHANNEL-LOGOUT dans le fichier des logs d’activité, qui indique l’URL d’envoie de logout token et la réponse de RP.

Configuration du Back-Channel Logout

Pour activer le Back-Channel Logout, il faut activer le back-channel logout dans OAuth2 Provider service et configurer l’URL de déconnexion back-channel dans le profil client de chaque RP. Par défaut, ils sont désactivés.

Activer le Back-Channel Logout dans OAuth2 Provider service

Deux attributs sont utilisés pour activer et configurer le back channel logout.

  • backChannelLogoutSupported pour activer le support du back-channel logout.
  • backChannelLogoutSessionSupported pour transmettre un sid (Session ID) dans le Logout Token (optionnel et configurable).

Configuration par IHM, dans le OAuth2 Provider service : oauth2provider device Configuration par ssoadm, dans le fichier de configuration Oauth2Provider, ajouter l’attribut backChannelLogoutSupported=true pour activer, et backChannelLogoutSessionSupported=true pour l’ajout de sid dans token.

Configurer l’URL de déconnexion back-channel dans le profil client

Configuration par IHM, dans le profil client : client profile

Configuration par l’outil ssoadm, ajouter l’attribut org.tosit.tosiam.backchannelLogout.uri= dans la configuration du client. Si un client n’a pas d’URL de déconnexion back-channel, il ne recevra pas de jeton de déconnexion. Pour ajouter un sid (Session ID) dans le Logout Token, ajouter l’attribut org.tosit.tosiam.backchannelLogout.sessionRequired=true.

Métadonnées de découverte OpenID Connect

L’OpenID Provider (OP) peut annoncer son support du Back-Channel Logout via les métadonnées de découverte OpenID Connect :

  • backchannel_logout_supported (booléen) : Indique si l’OP prend en charge le back-channel logout (par défaut false).
  • backchannel_logout_session_supported (booléen) : Indique si l’OP peut transmettre un sid (Session ID) dans le Logout Token.

https://localhost:8443/tosiam/oauth2/ref/.well-known/openid-configuration

{
"response_types_supported": [
"code",
"code token",
"token"
],
"claims_parameter_supported": false,
"introspection_endpoint": "https://localhost:8443/tosiam/oauth2/ref/introspect",
"end_session_endpoint": "https://localhost:8443/tosiam/oauth2/ref/connect/endSession",
"version": "3.0",
"check_session_iframe": "https://localhost:8443/tosiam/oauth2/ref/connect/checkSession",
"scopes_supported": [],
"backchannel_logout_supported": true,
"issuer": "https://localhost:8443/tosiam/oauth2/ref",
"id_token_encryption_enc_values_supported": [
"A128CBC-HS256",
"A256CBC-HS512"
],
"acr_values_supported": [],
"authorization_endpoint": "https://localhost:8443/tosiam/oauth2/ref/authorize",
"userinfo_endpoint": "https://localhost:8443/tosiam/oauth2/ref/userinfo",
"claims_supported": [],
"id_token_encryption_alg_values_supported": [
"RSA1_5"
],
"jwks_uri": "https://localhost:8443/tosiam/oauth2/ref/connect/jwk_uri",
"subject_types_supported": [
"public"
],
"id_token_signing_alg_values_supported": [
"ES384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512"
],
"registration_endpoint": "https://localhost:8443/tosiam/oauth2/ref/connect/register",
"token_endpoint_auth_methods_supported": [
"client_secret_post",
"private_key_jwt",
"client_secret_basic"
],
"backchannel_logout_session_supported": true,
"token_endpoint": "https://localhost:8443/tosiam/oauth2/ref/access_token"
}

Logout token

Le jeton de déconnexion est un JWT signé contenant les informations suivantes :

  • iss : Identifie l’OP qui a émis le token.
  • sub : Identifie l’utilisateur concerné.
  • aud : Indique la RP à qui le token est destiné.
  • jti : identifiant unique du jeton
  • iat : date de création du jeton
  • exp : date d’expiration du jeton
  • events: Contient http://schemas.openid.net/event/backchannel-logout, qui indique qu’il s’agit d’un Logout Token.
  • sid : (optionnel) identifiant de la session à fermer

Exemple de jeton de déconnexion :

{
  "sub": "demo",
  "aud": "rpa",
  "iss": "http://localhost:8080/tosiam/oauth2/ref",
  "exp": 1741792849,
  "iat": 1741789249,
  "jti": "78e8c587-24fc-4afb-8730-d6c939c5d31e",
  "events": {
  "http://schemas.openid.net/event/backchannel-logout": "{}"
  },
  "sid": "Mu6b6RPkZ7Ah0pr8qMiIiJpuTFY.*AAJTSQACMDEAAlNLABxhOWZzVExDZkJaNnhFWHVDdytsWnh5d0xiMk09AAJTMQAA*"
  }

Exemple Back-Channel Logout avec TOSIAM et des RP

Prérequis:

  • Sur votre machine Windows 10/11 ou Linux, installer Tosiam QuickStart. Nous supposons le serveur TOSIAM démarré.
  • Récupérer le projet GITHUB Tosiam Samples. Nous appellerons le répertoire de travail local <TOSIAM_SAMPLES>
  • Disposer d’un JDK 11+ (La variable JAVA_HOME est définie correctement)
  • Installer une version récente de nodejs/npm

Installation

Nous allons créer deux applications Relying Parties qui se connecteront à TOSIAM (OpenID Provider), et une application ressource protégée qui sera accessible par les RPs grâce à access_token. Nous configurerons ensuite le service OAuth2Provider afin d’activer le back-channel logout, et nous enregistrerons les URLs de déconnexion (logout URIs) des agents directement dans TOSIAM.

Les scripts nécessaires à la création de oauth2provier service et des agents oidc, les applications Relaying Party A et B, et la ressource protégée, sont situés dans le répertoire <TOSIAM_SAMPLES>/oidc_backchannel_logout, que nous appellerons <OIDC_BACKCHANNEL_LOGOUT>.

Relaying Party A

Pour info, ce tutoriel a été testé avec NodeJS version v18.19.1. Depuis le répertoire <OIDC_BACKCHANNEL_LOGOUT>/RPA, taper, sous windows ou sous linux:

npm install
npm start

L’application RP A démarre et est accessible sous http://localhost:4200

Relaying Party B

Depuis le répertoire <OIDC_BACKCHANNEL_LOGOUT>/RPB, taper, sous windows ou sous linux:

npm install
npm start

Protected Resource

Depuis le répertoire <OIDC_BACKCHANNEL_LOGOUT>/protected, taper, sous windows ou sous linux:

npm install
npm start

L’application RP A démarre et est accessible sous http://localhost:9001 L’application RP B démarre et est accessible sous http://localhost:9005 L’application ressource démarre et est accessible sous http://localhost:9002

Configuration dans TOSIAM

L’application TOSIAM démarre et est accessible sous http://localhost:8080/tosiam

Création du service Oauth2Provider et les agents oidc avec l’outil ssoadm

Ouvrez une fenêtre console dans le répertoire <OIDC_BACKCHANNEL_LOGOUT>/tosiam, et taper

  • Windows
  • Linux

set TOSIAM_HOME=<YOUR_INSTALL>
configure.bat
export TOSIAM_HOME=<YOUR_INSTALL>
./configure.sh

Tester le back-channel logout

Maintenant, les applications RPs sont prêtes à se connecter à TOSIAM, et TOSIAM est configuré pour gérer les connexions OIDC et le back-channel logout.

Connexion de l’application RP A

Depuis l’écran de connexion de l’application RP A, cliquer sur le bouton Get OAuth Token. Vous êtes redirigés vers la page d’authentification de TOSIAM. rpa.png login.png

Entrer:

  • Nom: dduck
  • Mot de passe: password

Vous arrivez sur la page de bienvenue de l’application. Notez la présence des informations d’access_token et de scopes et id_token.

index.png

Vous voyez s’afficher le contenu de l’Id Token, qui contient la sid (Session ID) parce que envoie de sid est activé dans TOSIAM.

{
  "header": {
    "typ": "JWT",
    "kid": "zhBofbZw+jkZZjXs28fGfzxZgM8=",
    "alg": "RS256"
  },
  "payload": {
    "at_hash": "BZOyz955GBZ9EDaKP37Oeg",
    "sub": "dduck",
    "auditTrackingId": "37f179a0-9c74-43fb-b284-d645eec77d8e-1359",
    "iss": "http://localhost:8080/tosiam/oauth2/ref",
    "tokenName": "id_token",
    "given_name": "Donald",
    "sid": "LmT6NhQSNdzbv3niUilVjqetovU.*AAJTSQACMDEAAlNLABxjR1ZObFpKc3dtQ2ZrYlY2SnBjNWtpR0Fqd1k9AAJTMQAA*",
    "aud": "rpa",
    "c_hash": "XIQOc1XW-3JrD4ZSK7HHwQ",
    "org.forgerock.openidconnect.ops": "921f7056-7879-4551-b371-5ff7ffdb56bf",
    "azp": "rpa",
    "auth_time": 1742512545,
    "name": "Donald DUCK",
    "realm": "/ref",
    "exp": 1742516145,
    "tokenType": "JWTToken",
    "iat": 1742512545,
    "family_name": "DUCK"
  },
  "signature": "XDVpv1Ji-qi4qcRIMxxprb2PR_Tlhn1jsYXGiFm5da4UunF8oORUIW1l9TlV12gekp8UWmWFDGv7pxqOtj7tnG1mSACT6B7vF9bE9iVPt7gyy5uDBn0krp8vtavZuPmDoZeOHUwmu3SRb7RzpJiSqXGdPAjwx1QUw3qAAqIDusOE97n4lYZxWvvAYFqvjioKGSPl-i3FfHElQWk2EiufCayGHxYLZukT8tMMJsAIRKIHUk_JJhVfKOkDjVHZOFXwmvU5DE8Rb3Qrw2jGW5bmg8FpB5MCR0I74AxzKhNVGS3zQLFDauW2seOrZJtLeHtRDZnnNaU4u6_pfpFvPKlYTg"
}

Connexion de l’application RP B

Depuis l’écran de connexion de l’application RP B, cliquer sur le bouton S’authentifier. Comme une session est déjà ouverte, vous êtes redirigés directement vers la page d’accueil de l’application, avec l’information d’access_token, scopes, id_token.

Vous voyez s’afficher le contenu de l’Id Token, qui contient la sid (Session ID) parce que envoie de sid est activé dans TOSIAM.

{
  "header": {
    "typ": "JWT",
    "kid": "zhBofbZw+jkZZjXs28fGfzxZgM8=",
    "alg": "RS256"
  },
  "payload": {
    "at_hash": "OS68uA1QwCJMpBC-pq4MQA",
    "sub": "dduck",
    "auditTrackingId": "37f179a0-9c74-43fb-b284-d645eec77d8e-1369",
    "iss": "http://localhost:8080/tosiam/oauth2/ref",
    "tokenName": "id_token",
    "given_name": "Donald",
    "sid": "LmT6NhQSNdzbv3niUilVjqetovU.*AAJTSQACMDEAAlNLABxjR1ZObFpKc3dtQ2ZrYlY2SnBjNWtpR0Fqd1k9AAJTMQAA*",
    "aud": "rpb",
    "c_hash": "CjB2YJLBSJJ1lHdLBm32kA",
    "org.forgerock.openidconnect.ops": "e3d96e7d-d1b7-4357-922f-0d06361e134d",
    "azp": "rpb",
    "auth_time": 1742512739,
    "name": "Donald DUCK",
    "realm": "/ref",
    "exp": 1742516339,
    "tokenType": "JWTToken",
    "iat": 1742512739,
    "family_name": "DUCK"
  },
  "signature": "ACLbiBcZTlaREstyhxRMBRS7W88LjI2vGzzhcxoYuVdcnHm-AqHS4v_kvYIDRbMxUsmesvNRHNOtrdnUIo3xp6Z-EHAG1-m-dVhdb9cucMYIWCqtYFbZv-4QmPvOBe5p40q2VLyLD_vuM5g5U1_bMgdVeny8hBdmTLCTFgdYbS_mr6shXKZy_gyDxvV3fqtYoqY3hz_MJbFQIQOPUwD9iV8Twrj_ayVa3XOk1ZajORjaoYvJI9F4n7KIRX9bp5EX5QtJNQqQGINf0EDBwE4-xZfLG54UPr0zJqcB8lW2G8T-QTB8hy-LqyeeKtPXMGyOy2mK_MJYlh5H1-Lfm7orcw"
}

Accès à la ressource protégée

Depuis l’application RP A, cliquer sur le bouton Get Protected Resource. RP A envoie une requête à la ressource protégée avec l’access_token. Vous êtes redirigés vers la page qui contient la ressource protégée de TOSIAM. protected.png

Déconnexion de l’application RP A

Maintenant les deux applications RP A et RP B sont connectées à TOSIAM et partagent la même session.

Cliquez sur le bouton Déconnexion de l’application RP A.

TOSIAM reçoit la demande de déconnexion et envoie un Logout Token à l’URL de déconnexion back-channel de RP A (http://localhost:9001/backchannel_logout). et de RP B (http://localhost:9005/backchannel_logout).

Logout token envoyé à RP A:

{
  "header": {
    "typ": "JWT",
    "kid": "zhBofbZw+jkZZjXs28fGfzxZgM8=",
    "alg": "RS256"
  },
  "payload": {
    "sub": "dduck",
    "aud": "rpb",
    "iss": "http://localhost:8080/tosiam/oauth2/ref",
    "exp": 1742516642,
    "iat": 1742513042,
    "jti": "b8a35480-8ca0-4b81-a403-0d7aed722c89",
    "events": {
      "http://schemas.openid.net/event/backchannel-logout": "{}"
    },
    "sid": "LmT6NhQSNdzbv3niUilVjqetovU.*AAJTSQACMDEAAlNLABxjR1ZObFpKc3dtQ2ZrYlY2SnBjNWtpR0Fqd1k9AAJTMQAA*"
  },
  "signature": "lPfD7z4QZmPcxXSPp5YefkBkKkq3teHOL1uTItipLhTsiloO5e5kgtZbLSGpKnVDfjvQHO-rodfNuAOx7dyy-wyVaqwLSphuJqLm3nz5lmW30jb4yb9cE3HwVU-lGiCmLi-JTmKmEJ2Lq41gdAtUacE1TzyUBmVF9mxDL_V3eT778rvehBoi505Y6FYoSBjDJGJR3Z1AIvYvQOhrLBgyNTX7ELizYMX7JwdWUy9DQJSno3uFAKKtOxathi1u-6hn_SyKoT4Cd52Nm1o7_zgRWIDOxppqprz941Yno_FMHS5JDN3lHAYhTkQM-K__oiI_6tZGHVzWdDuZYUmNZ4IxRw"
}

Logout token envoyé à RP B:

{
  "header": {
    "typ": "JWT",
    "kid": "zhBofbZw+jkZZjXs28fGfzxZgM8=",
    "alg": "RS256"
  },
  "payload": {
    "sub": "dduck",
    "aud": "rpb",
    "iss": "http://localhost:8080/tosiam/oauth2/ref",
    "exp": 1742516642,
    "iat": 1742513042,
    "jti": "b8a35480-8ca0-4b81-a403-0d7aed722c89",
    "events": {
      "http://schemas.openid.net/event/backchannel-logout": "{}"
    },
    "sid": "LmT6NhQSNdzbv3niUilVjqetovU.*AAJTSQACMDEAAlNLABxjR1ZObFpKc3dtQ2ZrYlY2SnBjNWtpR0Fqd1k9AAJTMQAA*"
  },
  "signature": "lPfD7z4QZmPcxXSPp5YefkBkKkq3teHOL1uTItipLhTsiloO5e5kgtZbLSGpKnVDfjvQHO-rodfNuAOx7dyy-wyVaqwLSphuJqLm3nz5lmW30jb4yb9cE3HwVU-lGiCmLi-JTmKmEJ2Lq41gdAtUacE1TzyUBmVF9mxDL_V3eT778rvehBoi505Y6FYoSBjDJGJR3Z1AIvYvQOhrLBgyNTX7ELizYMX7JwdWUy9DQJSno3uFAKKtOxathi1u-6hn_SyKoT4Cd52Nm1o7_zgRWIDOxppqprz941Yno_FMHS5JDN3lHAYhTkQM-K__oiI_6tZGHVzWdDuZYUmNZ4IxRw"
}

L’utilisateur est déconnecté de RP A et de RP B. L’application RP A affiche un message de déconnexion.

logout.png

Cliquez sur le bouton Get Protected Resource de l’application RP B. L’accès à la ressource protégée est bloqué, car l’access_token n’est plus valide.

protected_logout.png

Comment la RP traite-t-elle cette requête POST

Validation du Logout Token par la RP

Lors de la réception d’un Logout Token, la RP doit :

  1. Déchiffrer le token (si chiffré).
  2. Vérifier la signature JWT.
  3. Valider les claims : iss, aud, iat, exp, jti, events.
  4. S’assurer que le token contient sub ou sid.
  5. Rejeter tout Logout Token contenant nonce.
  6. Optionnellement, vérifier que le Logout Token n’a pas déjà été reçu.

Si une validation échoue, la RP retourne une erreur HTTP 400.

Actions de Logout par la RP

  • La RP trouve la session utilisateur concernée (via sub et sid).
  • Elle supprime la session et les informations associées.
  • Si la RP est aussi un OP (cascade d’authentification), elle peut propager la demande de logout.

Réponse au Back-Channel Logout

  • Succès : HTTP 200 OK (ou 204 No Content).
  • Erreur : HTTP 400 Bad Request avec une description JSON optionnelle.

Exemple d’en-tête recommandé : http Cache-Control: no-store (pour empêcher la mise en cache de la réponse).

Exemple de réponse de RP A"

{
  "status": "ok"
}

Log de TOSIAM:

b492af7e-b913-452a-8a05-d177789b1ad1-132	2025-03-21T14:22:31.451Z	AM-BACK-CHANNEL-LOGOUT	b492af7e-b913-452a-8a05-d177789b1ad1-124	
id=dduck,ou=user,o=ref,ou=services,dc=tosit,dc=org	["a762ce1eceb4d25301"]	id=dsameuser,ou=user,dc=tosit,dc=org	
a762ce1eceb4d25301	Send Back channel logout request to http://localhost:9001/backchannel_logout which returned the HTTP Status-Code 200