Documents:Single Sign Out
Un article de Wiki ESCO-Portail.
Sommaire |
Principe et fonctionnement
Depuis la version 3.x, CAS gère le Single Sign-Out. Ce mécanisme permet à un utilisateur, lorsqu'il se déconnecte d'une application cassifiée, d'être déconnecté de toutes les applications qui profitaient de cette authentification CAS.
(See https://wiki.jasig.org/display/CASUM/Single+Sign+Out)
Le fonctionnement du Single Sign-Out (ou Global Logout) avec CAS est le suivant :
1) L'utilisateur se connecte à une application A, qui demande une authentification auprès du serveur CAS
2) L'utilisateur accède à une autre application B, qui profite de l'authentification CAS précédemment demandée.
3) Lorsque l'utilisateur se déconnecte, depuis le portail proposant les 2 applications (par exemple), le portail informe CAS qu'il souhaite terminer la session de l'utilisateur.
C'est à ce moment que le mécanisme de Single Sign-Out intervient. Lorsque CAS reçoit la demande de fermeture de session, il informe toutes les autres applications qui profitaient de l'authentification CAS que cette session n'est plus utilisable.
Pour informer les applications, CAS effectue une requête POST en HTTP sur l'URL que chaque application lui à fournis lors de la demande d'authentification.
Cette requête contient entre autres l'identifiant du ticket cas (ST) qui n'est plus utilisable.
Du côté de l'application, 2 méthodes possibles :
Traitement de la requête de logout à la main
On s'occupe manuellement dans application de récupérer la requête de logout de cas, c'est à dire, extraire l'identifiant du ticket cas concerné, et clore la session applicative correspondante.
Détails des modifications effectuées pour chaque application
- Modifications pour Moodle : Modifications de Moodle pour Single Sign-Out CAS
- Modifications pour Grr : Modifications de Grr pour Single Sign-Out CAS
Traitement de la requête via handleLogoutRequest() de phpCAS
La librairie phpCAS intègre la fonction handleLogoutRequest qui permet :
- de définir une liste blanche de serveurs cas dont les requêtes de logout seront traitées (toutes les autres seront ignorées ; ce mécanisme sert à se protéger contre les attaques DOS basées sur l'envoi de fausses requêtes de logout)
- de traiter la requête et de terminer la session correspondante.
Cette fonction présente une subtilité importante :
Cas étant l'initiateur de la requête de logout, il est théoriquement impossible de terminer la session de l'utilisateur à déconnecter. La solution connue qui a été mise en place ici était de passer par des sessions gérées en base de données. Ainsi, lors de la réception de la requete par l'application, il suffit de faire une requête sur la bonne table pour détruire la session.
La fonction handleLogoutRequest() (présente visiblement depuis phpCAS 1.0.0) semble apporter une solution intéressante (Voir l'extrait du code) :
// fix New session ID session_id($session_id); $_COOKIE[session_name()]=$session_id; $_GET[session_name()]=$session_id; // Overwrite session session_start(); session_unset(); session_destroy();
Elle utilise la fonction session_id() de php, non pas pour récupérer un session_id, mais pour le fixer ! Ainsi, selon la doc de php, lorsque l'on effectuera un session_start(), on démarrera une session ayant pour identifiant le session_id fourni précédemment.
Elle défini ensuite un cookie et lui donne la valeur du session_id. (certainement pour faire croire que la session est ouverte ici)
Elle créé une variable GET, certainement dans le même but.
Puis elle démarre la session, détruit tout son contenu, et détruit la session elle-même.
En fait, il semble que l'on "spoof" en quelque sorte la session de l'utilisateur (on se fait passer pour...) afin de la détruire.
Après Tests, la fonction handleLogoutRequest fonctionne bien selon ce principe, et cas parvient bien à terminer la session de l'utilisateur en "se faisant passer pour lui".
Un point important est tout de même à noter :
Pour que ce mécanisme fonctionne, il faut avoir autorisé phpCAS (et notamment phpCAS::Client()) à ouvrir lui même la session PHP.
C'est important car du coup, la session est ouverte avec comme "session_id" le Ticket CAS, duquel les tirets sont supprimés. (exemple : ST69OmUntkXO1IKlm6zJIO1cas). Dans le cas contraire, l'identifiant de session est simplement généré par PHP, et le code vu précédemment sera incapable de terminer la session. En détails, la fonction handleLogoutRequest
- Récupère le session_id (ticket cas sans les tirets) depuis la requete de logout,
- exécute session_id($session_id); pour que la future session ouverte par session_start() ait cet identifiant (~spoofing)
Or, si la session a été ouverte par phpCAS::Client(...,...,...,false), alors le session_id sera celui généré par php (et non le ticket cas). Donc, ce ne sera pas la bonne session qui sera fermée, mais une session certainement inexistante.
Il faut donc appeler phpCAS::Client (ou phpCAS::Proxy...) avec true, et non avec false, sur le paramètre qui l'autorise à ouvrir la session lui même
Applications modifiées pour le Global Logout sur l'ENT
| Application | Test | Démo | Production |
| Cahier de Texte Caen | OK | . | OK |
| Moodle | OK | . | OK |
| Grr | OK | OK | OK |
| GEPI | . | . | . |
| Sarapis UI | . | . | . |
| Esup Portail | . | . | . |

