Tutoriel sur l'authentification centralisée SSO via le protocole CAS

Gauthier Perrineau

Dans le cadre d'un site web ou d'un intranet distribué se pose la problématique du partage de l'authentification entre les différents services. Cette problématique peut être résolue grâce à un service tiers chargé de centraliser l'authentification et de partager un identifiant unique d'utilisateur avec chacun des services. Dans cet article nous nous intéresserons au SSO CAS de Jasig, et à la mise en place d'une preuve de faisabilité très simple permettant de mieux étudier le protocole CAS.
Commentez

- Titre : Tutoriel sur l'authentification centralisée SSO via le protocole CAS

- Auteur : Gauthier Perrineau

- Parution : 19 novembre 2013

- Licence : Copyright ® 2013 Gauthier Perrineau. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Les différents types d'authentification unique.

- II. Présentation du SSO CAS

- III. Le protocole CAS : explication simplifiée

- III-A. Introduction

- III-B. Première authentification

- III-C. Accès à une deuxième application reliée au SSO

- III-D. Déconnexion du SSO

- IV. Installation d'une maquette de faisabilité (POC)

- IV-A. Préparation

- IV-B. Import et configuration des projets

- IV-B-1. Import des war dans Eclipse

- IV-B-2. Configuration du projet MyWebApp en HTTP simple

- IV-B-3. Ajout des dépendances supplémentaires au projet mywebapp

- IV-B-4. Déploiement dans le serveur d'applications

- IV-C. Test en HTTP

- IV-D. Test en HTTPS

- IV-E. Exemple de logout

- V. Débogage

- VI. Pour aller plus loin?

- Conclusion

- Remerciements

I - Les différents types d'authentification unique.

Pour une présentation générale de l'authentification unique, je vous invite à consulter la présentation qu'en fait Wikipédia. Quelques clés de lecture :

- dans le cadre d'une entreprise qui possède ses propres serveurs et héberge elle-même son site internet, on peut faire en sorte que l'ensemble des utilisateurs passent par un firewall commun et placer un filtre au niveau des frontaux d'entrée pour forcer l'authentification à ce niveau, puis mettre en place un mécanisme qui permettra à chacun des modules qui composent le site internet de récupérer les identifiants de leurs visiteurs (approche centralisée) ;

- cependant cette solution qui se prête bien à un intranet d'entreprise, se prête moins à un site de e-commerce, qui souhaite évidemment que les clients potentiels puissent accéder aux pages d'achat sans avoir à s'authentifier, renvoyant cette étape au plus tard possible. Par ailleurs les sites de e-commerce peuvent mettre en place des partenariats avec des sites tiers autorisés à vendre leurs articles, mais avec des réductions pour leurs adhérents, ce qui suppose de leur déléguer d'une manière ou d'une autre les informations d'authentification. Dans un cas comme celui-là il y a deux solutions :

- dans le cadre de l'approche fédérative (ou décentralisée), on va laisser chacun des services frontaux gérer son propre système d'authentification tout en partageant l'ID de session utilisateur avec les services tiers dont il dépend. Cette solution est potentiellement dangereuse en cas d'interdépendances entre les services, et de plus elle est peu ergonomique, car l'utilisateur peut alors avoir plusieurs sessions ouvertes en même temps avec différents logins, différentes fiches clients? Ce qui peut s'avérer très complexe dans certains cas d'usage,

- dernière possibilité, dans l'approche coopérative l'ensemble des services qui composent le site internet délèguent ce qui relève de la problématique d'authentification à un service tiers et se tournent vers lui pour connaître le numéro du client lorsqu'ils ont besoin d'autoriser ce dernier à accéder à du contenu protégé. Cela suppose également la centralisation des fiches clients dans des backends mutualisés. C'est l'approche mise en place par le CAS, que nous allons évoquer dans ces lignes.

On distinguera authentification sécurisée et sécurité de l'application. Dans le cadre de l'approche centralisée, les deux peuvent être gérées au même niveau. Par contre dans le cadre de l'approche fédérative et de l'approche coopérative, il revient à chaque application d'appliquer sa propre politique de sécurité. Nous vous suggérons par exemple d'utiliser spring-security, qui supporte nativement l'intégration du CAS.

II - Présentation du SSO CAS

Le SSO (acronyme de Single Sign On) CAS (acronyme de Central Authentication Service) est une solution d'authentification centralisée open source originellement développée par l'université de Yale et reprise depuis par Jasig, qui est très répandue dans les réseaux intranet d'universités, mais également utilisée dans certaines entreprises.

Nous l'avons vu déployé sur le site internet d'une entreprise qui absorbait sans problème une charge pouvant monter à 1000 requêtes d'authentification par seconde en pic avec une répartition de charge sur trois serveurs, ce qui témoigne à la fois de la pertinence de son utilisation en production sur un site à fort trafic, et de son intérêt comparativement à certaines solutions payantes bien moins satisfaisantes.

L'architecture d'un système basé sur CAS est très simple : comme le CAS est écrit en Java, vous avez simplement besoin d'un serveur d'applications (Jetty, Tomcat, etc.) pour y déployer le serveur. Intégrez ensuite dans chacun des modules qui composent votre site un client CAS applicatif, qui sera chargé de gérer la communication avec le serveur CAS et l'authentification de vos utilisateurs. L'une des grandes forces du CAS, c'est qu'il utilise un protocole HTTP standard, il n'y a donc aucune contrainte sur le choix du langage à utiliser pour coder votre site internet, il est même possible d'avoir un parc hétérogène. De nombreux clients existent déjà, notamment en Java, .Net et PHP.

Nous vous renvoyons une fois de plus à Wikipédia pour une description plus détaillée. Vous pouvez également consulter la page qui lui est consacrée par les Mines de Paris.

III - Le protocole CAS : explication simplifiée

Dans la partie IV, nous montrerons comment installer un serveur CAS, comment configurer des clients pour interagir avec lui, et comment observer que l'authentification SSO a bien lieu. Les plus pressés peuvent dès maintenant y jeter un coup d??il pour se faire une idée. Mais avant d'y venir, il est important que nous exposions brièvement le mode de fonctionnement du protocole CAS.

III-A - Introduction

Nous nous limiterons ici à une présentation simplifiée du protocole CAS. En cas de doute, se reporter à cette page (en anglais) qui constitue une référence sur le sujet. Rappelons que nous nous situons dans le contexte d'un système d'authentification où les clients se connectent par le biais de leur navigateur à des applications web qui ont chacune leur propre contexte. Chacune de ces applications est par ailleurs raccordée au serveur CAS auquel est déléguée la gestion de l'authentification. Il convient d'être bien au clair sur la distinction entre le client (l'utilisateur final via son navigateur internet), application (couplée à un client CAS, c'est un module de votre site internet) et serveur CAS, car ces termes seront employés de manière intensive dans la suite.

Par ailleurs le protocole CAS est principalement basé sur le SSL, le protocole HTTP (voir la liste des codes retour HTTP et les cookies (cryptés ou non). En conséquence, si vous n'êtes pas à l'aise avec ces notions, je vous suggère de faire un rapide tour sur les pages concernées.

III-B - Première authentification

Diagramme de séquence d'une authent CAS

(cliquez ici pour aggrandir l'image)

Lorsqu'un client accède à une application reliée au SSO CAS pour la première fois, celle-ci va détecter un utilisateur anonyme, lui créer une session avec le rôle ANONYMOUS, et le laisser libre de visiter le contenu non protégé. Lors du clic sur un lien menant à une ressource protégée (1), l'application va renvoyer au client une redirection (code 302) vers le serveur CAS en lui passant en paramètre un serviceID (2a,b). Ce service ID est en fait une URL qui permettra au serveur CAS d'identifier l'application qui a redirigé le client vers lui. Le serveur CAS affiche alors au client un formulaire d'authentification (3), pour qu'il y rentre son login et son mot de passe (4).
Une fois que le client aura réussi à s'authentifier, le serveur CAS va faire trois choses :

- déposer un cookie de session sécurisé CASTGC (acronyme qui signifie CAS Ticket Granting Cookie) sur le chemin /cas. C'est le cookie sur lequel repose la partie SSO de l'authentification. Il s'agit d'un cookie de session qui va donc persister jusqu'à la fermeture du navigateur ou l'expiration de la session HTTP (généralement après 15 minutes d'inactivité) ;

- ensuite il va générer un service ticket (ST). Il s'agit d'un nombre aléatoire sans signification particulière. Le serveur CAS le stocke dans sa mémoire et l'associe à l'identifiant du client. La durée de vie du service ticket est très brève : de l'ordre de quelques secondes ;

- enfin le serveur CAS va contrôler que le service ID que lui a fourni le client correspond bien à un service qui lui est raccordé, puis rediriger à son tour le client vers l?URL correspondant au service ID, en lui donnant le service ticket en paramètre GET (5a,b).

Le client va donc charger à nouveau une page de l'application sur laquelle il était connecté au début. Celle-ci va récupérer le service ticket dans la requête de redirection, et cette fois-ci elle va appeler directement le serveur CAS en mode M2M en lui donnant le service ticket (6). Le serveur CAS vérifie que l'URL de l'application est bien une URL enregistrée, contrôle que c'est bien cette URL qui est associée au ticket, et répond l'identifiant qui correspond au client qui vient tout juste de s'identifier (7).

Après cela, l'application sait que le client a réussi à s'authentifier sur le serveur CAS, elle peut donc lui attribuer le rôle AUTHENTICATED et le laisser accéder au contenu protégé. Par ailleurs, maintenant qu'elle connaît l'identifiant du client, elle peut interroger sa base de données ou un web service centralisé chargé d'agréger les données client pour récupérer les informations de ce client (sa fiche utilisateur), et lui afficher un contenu adapté à son profil.

Il est possible de désactiver complètement le HTTPS pour les besoins du débogage en environnement de développement et de déposer alors le cookie CASTGC en clair, mais il est indispensable de l'activer en production, car la sécurité du protocole s'appuie dessus, et en particulier il serait mal venu que le cookie CASTGC circule en clair sur le réseau.

III-C - Accès à une deuxième application reliée au SSO

Lorsqu'un client qui s'est authentifié sur une première application essaye d'accéder au contenu protégé d'une deuxième application, celle-ci va réagir de la même manière que la première, à savoir qu'elle va le rediriger sur le serveur CAS au moyen d'un 302 HTTPS avec son serviceID en paramètre. Le serveur CAS va alors observer que le client possède un cookie sécurisé CASTGC. Si celui-ci est valide, il va en extraire l'identifiant de l'utilisateur. Du coup il va considérer celui-ci comme déjà authentifié et sauter l'étape de l'affichage de la mire d'authentification.

La conséquence, c'est que dans le cas nominal, le client ne va même pas se rendre compte qu'il a été redirigé vers le serveur CAS. Après deux redirections successives, il accédera au contenu protégé de la deuxième application sans avoir eu à rentrer à nouveau son login et son mot de passe utilisateur.

Si vous souhaitez comprendre plus en détail la cinématique d'authent, je vous recommande le diagramme de séquence suivant (en anglais), qui a été proposé par David Ohsie sur la mailing list CAS, et qui permet de suivre le détail des requêtes https.

Diagramme de séquence complet (en anglais)

(cliquez ici pour aggrandir l'image)

III-D - Déconnexion du SSO

Dans le cadre d'une application non raccordée à un SSO, la déconnexion se fait tout simplement : l'application expose un lien de déconnexion qui va provoquer l'invalidation de la session du client lorsque celui-ci va cliquer dessus. Dans le cadre d'un SSO un tel mécanisme ne déconnecterait pas le client du SSO mais seulement d'une des applications du SSO. Par conséquent un mécanisme un peu plus élaboré est requis.

Si le client souhaite mettre fin à son authentification SSO, il est possible d'appeler une URL /cas/logout du serveur CAS pour lui demander de détruire le cookie CASTGC. Dans la version actuelle du serveur CAS il y a alors un mécanisme qui fait que le serveur CAS, ayant mémorisé l'ensemble des applications sur lesquelles le client s'est authentifié va rappeler chacune d'entre elles en M2M pour lui indiquer d'invalider la session associée à ce client.

IV - Installation d'une maquette de faisabilité (POC)

On reproche souvent à la documentation officielle du CAS son opacité. Pourtant celle-ci est très complète et couvre un grand nombre de cas de figure. Dans le cadre de ce tutoriel, nous nous limiterons au cas le plus simple possible dans le but de vous permettre d'étudier le protocole CAS de l'intérieur à partir d'un exemple fonctionnel, plutôt que d'essayer de se lancer directement dans un déploiement complexe. Ce qui va suivre est librement inspiré du tutoriel JA-SIG Java Client Simple WebApp Sample de la documentation officielle avec quelques simplifications qui vous permettront d'aboutir à quelque chose de fonctionnel en quelques minutes.

Le tutoriel a été testé sur Windows 7, avec Eclipse Juno SR2 (version développeurs J2EE), le JDK 7u21, et Apache-Tomcat-7.0.40. Dans le tutoriel sur lequel nous nous appuyons, l'auteur utilisait une version de Tomcat v5.5.25, ce qui est signe qu'a priori le serveur CAS est relativement agnostique des choix que vous ferez en termes d'infrastructure.

Dans les paragraphes qui vont suivre, nous vous expliquons comment effectuer toute la configuration en pas à pas à partir d'Eclipse. Mais il est possible de parvenir au même résultat beaucoup plus rapidement via Maven.
Installez simplement une machine Java et Maven. Téléchargez ensuite suivant la version de votre JDK le projet Maven de ce tutoriel : Demo SSO CAS JDK7 ou Demo SSO CAS JDK6, décompressez-le, naviguez en ligne de commande jusqu'au répertoire qui comporte le pom et tapez: « mvn jetty:run ».
Patientez jusqu'à la fin du build, il est probable que celui-ci dure plusieurs minutes la première fois. L'étape « Adding virtual project first in resource base list » peut prendre un moment, ne vous inquiétez pas s'il ne se passe rien. Lorsque la console affiche « [INFO] Started Jetty Server », le serveur est démarré, vous pouvez passer au test en HTTPS du IV-D.
N.B. Pour une raison que je n'ai pas encore élucidée, il arrive que des erreurs SSL fassent rater le test lors du premier lancement. Si cela se produit, interrompez le processus en cours (CTRL+C) et relancez-le dans le même terminal.

IV-A - Préparation

Si ce n'est pas déjà fait, téléchargez et installez un JDK (par exemple le dernier). De même, téléchargez la dernière version de Tomcat correspondant à votre système. Il n'y a pas d'installateur, il suffit de décompresser l'archive dans le dossier d'installation. Enfin, téléchargez et installez Eclipse dans la version qui vous siéra. Lancez Eclipse pour la première fois, ajoutez un nouveau serveur pointant sur le répertoire d'installation de votre Tomcat, et éditez le chemin de la JVM qui doit a priori pointer par défaut sur votre JRE système et que vous avez besoin de faire pointer sur votre JDK nouvellement installé. Nous ne détaillerons pas outre mesure tout ce processus qui ne constitue pas le c?ur du tutoriel et qui est déjà abondamment traité par ailleurs.

Maintenant que votre environnement de développement est prêt, nous allons préparer nos projets.

- Téléchargez la dernière version du serveur CAS : à l'heure où nous écrivons ces lignes, il s'agit de la 3.5.2. Dézippez l'archive, et naviguez dans le dossier « modules » jusqu'au ficher « cas-server-webapp-VERSION.war ». Renommez-le simplement en « cas.war ».

- Téléchargez le sample de démonstration.

- Téléchargez les dépendances du sample de démonstration. Vous aurez besoin du client CAS Java (nous avons pour notre part utilisé la version 3.2.1) et de Xerces2 pour Java (nous avons pour notre part utilisé la version 2.11.0)

IV-B - Import et configuration des projets

IV-B-1 - Import des war dans Eclipse

Pour chacune de nos deux archives cas.war et webapp.war, effectuez les manipulations suivantes :

- depuis Eclipse, cliquez sur Fichier, Import, et choisissez l'import d'une archive WAR ;

- sélectionnez le serveur Tomcat nouvellement configuré, puis cliquez sur « suivant » ;

- dans la fenêtre suivante, vérifiez simplement que toutes les dépendances seront bien copiées dans le dossier WEB-INF/lib puis cliquez sur « Terminer ».

IV-B-2 - Configuration du projet MyWebApp en HTTP simple

Le projet mywebapp est configuré par défaut pour utiliser du SSL. Dans le cadre de notre exemple, nous préférons sauter cette étape pour le moment, mais nous y reviendrons ultérieurement.

- Éditez le fichier de configuration web.xml du projet mywebapp (dans l'arborescence projet il est situé dans WebContent/WEB-INF/).

- Remplacez toutes les occurrences de «https://localhost:8443 » par « http://localhost:8080 ».

- De même, toutes les occurrences de « https://localhost/ » par « http://localhost:8080/ ».

IV-B-3 - Ajout des dépendances supplémentaires au projet mywebapp

- Dans la bibliothèque de client CAS que vous avez téléchargée, allez dans le dossier « modules » et récupérez les archives « cas-client-core-3.2.1.jar », « commons-logging-1.1.jar » et « xmlsec-1.3.0.jar ».

- Dans l'archive de xerces que vous avez téléchargée, récupérez les bibliothèques « xercesImpl.jar » et « xml-apis.jar »,

- puis copiez-collez ces cinq bibliothèques dans le dossier « WebContent/WEB-INF/lib » de l'application mywebapp.

- Enfin, relancez la construction du projet pour qu'elles soient bien prises en compte par toutes les JSP.

IV-B-4 - Déploiement dans le serveur d'applications

- Dans l'onglet « Servers » d'Eclipse, faites un clic droit sur votre serveur Tomcat,

- choisissez « Add and remove » puis « Add all » et confirmez.

- Enfin, faites un nouveau clic droit sur votre serveur Tomcat et choisissez « Start ».

- Votre serveur et vos applications sont désormais démarrés.

Attention dans un but de simplification à l'extrême, nous utilisons le même serveur Tomcat pour le serveur CAS et pour l'appli de démo. Gardez cependant à l'esprit que dans un contexte de production, le serveur CAS et chacun des services qui lui sont raccordés seront déployés dans des instances Tomcat différentes, potentiellement situées sur des serveurs physiques différents et que leur seul mode de communication est donc la couche réseau.

IV-C - Test en HTTP

Maintenant que votre environnement est prêt et que votre serveur CAS et votre webapp sont configurés et démarrés, nous allons effectuer un premier test en HTTP.

- Rendez-vous sur l'URL http://localhost:8080/mywebapp pour accéder à votre appli de démo.

- Cliquez sur le lien « got to protected area ».

- Observez dans l'URL que vous êtes redirigés vers une URL de type « http://localhost:8080/cas/login?service=http%3A%2F%2Flocalhost%3A8080%2Fmywebapp%2Fprotected%2F ». Ce qu'il faut noter, c'est que le contexte a changé, vous n'êtes plus dans le contexte de votre application « mywebapp », mais dans celui du serveur CAS.

- Rentrez n'importe quel couple login/mot de passe. Par défaut, il suffit que le login et le mot de passe soient identiques pour que l'authentification réussisse.

- Vous êtes alors redirigés vers la page http://localhost:8080/mywebapp/protected/. Vous observerez que le contexte a rechangé, vous êtes de retour sur votre application et vous avez accès au contenu protégé.

- Cliquez sur le lien « public area », vous êtes envoyé sur la page originelle, recliquez sur le lien « go to protected area », vous retournez dans la zone protégée, sans être cette fois-ci redirigé sur le serveur CAS car l'application connaît déjà votre identifiant.

À ce stade si vous observez des erreurs de chargement ou des exceptions de type « connexion refusée », c'est probablement lié à un oubli dans la modification du fichier web.xml.

Pour que le test soit probant, il faudrait déployer une deuxième instance de l'application mywebapp. Vous pouvez tout simplement copier-coller l'archive war et la renommer par exemple « mywebapp2.war » puis la réimporter dans Eclipse, la configurer de la même manière que la première, mais en n'oubliant pas de changer son nom entre les balises « display-name » du fichier « web.xml ». Ensuite de quoi, ajoutez-la au serveur Tomcat et redémarrez tout. Refaites le même test que précédemment puis rendez-vous sur votre deuxième appli http://localhost:8080/mywebapp2/ et cliquez sur le lien « go to protected area ».

Votre serveur Tomcat

Dans un contexte SSO, vous devriez être authentifié automatiquement sans être redirigé vers le serveur CAS, puisque vous vous êtes déjà authentifié sur la première application?
Oui mais? Vous observerez sans doute que la redirection est faite quand même et c'est tout à fait normal. En effet la sécurité du protocole CAS repose de manière intensive sur le protocole SSL, et c'est via le cookie crypté CASTGC que l'authentification est partagée. Du coup en forçant l'utilisation du protocole HTTP, nous avons empêché que ce cookie soit utilisé. Pour aller plus loin, nous allons donc devoir reprendre notre configuration et accéder à notre serveur CAS en HTTPS

IV-D - Test en HTTPS

La première chose à faire, si vous n'avez jamais configuré le SSL de votre poste est de générer le certificat SSL, de paramétrer Tomcat pour qu'il l'utilise, puis de le stocker dans vos certificats acceptés pour permettre la communication M2M. Nous avons évoqué la procédure à suivre dans notre autre cours Mise en place d'une communication SSLautosignéede machine à machine en Java .

Ceci fait, éditez à nouveau les deux fichiers web.xml de vos applications jumelles mywebapp et mywebapp2. Cette fois-ci nous allons configurer l'ensemble des URL qui y sont déclarées pour qu'elles soient de la forme « https://localhost:8443/ ». Enregistrez les fichiers, redémarrez le serveur Tomcat et refaites un test.

- Allez sur la première webapp l'URL doit désormais être https://localhost:8443/mywebapp/),

- essayez d'accéder au contenu protégé (soit https://localhost:8443/mywebapp/protected/),

- observez la redirection vers le serveur CAS et rentrez un login et un mot de passe identiques,

- et enfin observez que vous êtes à nouveau redirigé, cette fois-ci vers l'espace protégé de la première appli.

Première connexion sur Webapp1

Redirection sur le formulaire d'authentification du serveur CAS

Après une authentification réussie, accès à l'espace protégé de webapp1

Logs observés dans la console durant le processus

2013-09-14 19:18:06,896 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: [username: example]
WHAT: supplied credentials: [username: example]
ACTION: AUTHENTICATION_SUCCESS
APPLICATION: CAS
WHEN: Sat Sep 14 19:18:06 CEST 2013
CLIENT IP ADDRESS: 0:0:0:0:0:0:0:1
SERVER IP ADDRESS: 0:0:0:0:0:0:0:1
=============================================================

>
2013-09-14 19:18:06,899 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: [username: example]
WHAT: TGT-1-lcyDdbynZWtxpPp6fc7bsQO4Vm0lYKmEbpgp6vL9x6oxFT7qAe-cas01.example.org
ACTION: TICKET_GRANTING_TICKET_CREATED
APPLICATION: CAS
WHEN: Sat Sep 14 19:18:06 CEST 2013
CLIENT IP ADDRESS: 0:0:0:0:0:0:0:1
SERVER IP ADDRESS: 0:0:0:0:0:0:0:1
=============================================================

>
2013-09-14 19:18:06,902 INFO [org.jasig.cas.CentralAuthenticationServiceImpl] - <Granted service ticket [ST-1-ljGDvgc5XGBkjRvausFQ-cas01.example.org] for service [https://localhost:8443/mywebapp/protected/] for user [example]>
2013-09-14 19:18:06,902 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: example
WHAT: ST-1-ljGDvgc5XGBkjRvausFQ-cas01.example.org for https://localhost:8443/mywebapp/protected/
ACTION: SERVICE_TICKET_CREATED
APPLICATION: CAS
WHEN: Sat Sep 14 19:18:06 CEST 2013
CLIENT IP ADDRESS: 0:0:0:0:0:0:0:1
SERVER IP ADDRESS: 0:0:0:0:0:0:0:1
=============================================================

>
2013-09-14 19:18:07,001 INFO [org.jasig.cas.authentication.AuthenticationManagerImpl] - <org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler successfully authenticated [callbackUrl: https://localhost:8443/mywebapp/proxyCallback]>
2013-09-14 19:18:07,001 INFO [org.jasig.cas.authentication.AuthenticationManagerImpl] - <Resolved principal https://localhost:8443/mywebapp/proxyCallback>
2013-09-14 19:18:07,001 INFO [org.jasig.cas.authentication.AuthenticationManagerImpl] - <org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler@ff49ab authenticated https://localhost:8443/mywebapp/proxyCallback with credential [callbackUrl: https://localhost:8443/mywebapp/proxyCallback].>
2013-09-14 19:18:07,002 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: [callbackUrl: https://localhost:8443/mywebapp/proxyCallback]
WHAT: supplied credentials: [callbackUrl: https://localhost:8443/mywebapp/proxyCallback]
ACTION: AUTHENTICATION_SUCCESS
APPLICATION: CAS
WHEN: Sat Sep 14 19:18:07 CEST 2013
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: 127.0.0.1
=============================================================

>
2013-09-14 19:18:07,002 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: example
WHAT: TGT-2-zrJ3bI7PIBZ7cM9oYfFUexHYZQX1PleeRMXAgdpt2NTIOPU1zD-cas01.example.org
ACTION: PROXY_GRANTING_TICKET_CREATED
APPLICATION: CAS
WHEN: Sat Sep 14 19:18:07 CEST 2013
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: 127.0.0.1
=============================================================

>
2013-09-14 19:18:07,005 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: audit:unknown
WHAT: ST-1-ljGDvgc5XGBkjRvausFQ-cas01.example.org
ACTION: SERVICE_TICKET_VALIDATED
APPLICATION: CAS
WHEN: Sat Sep 14 19:18:07 CEST 2013
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: 127.0.0.1
=============================================================

>

Petit commentaire sur ces logs, concentrez-vous sur la valeur du champ « ACTION ». Il faut remarquer notamment les valeurs AUTHENTICATION_SUCCESS, qui indique une authentification réussie, TICKET_GRANTING_TICKET_CREATED qui est relatif à la pose du cookie CAS, et SERVICE_TICKET_CREATED qui indique la création d'un ticket (voir en deuxième partie les explications sur le protocole CAS). Ensuite dans les logs qui suivent, faites également attention au champ WHO. La deuxième apparition de AUTHENTICATION_SUCCESS concerne cette fois-ci webapp1 qui s'est connecté au serveur CAS pour valider le ticket, et SERVICE_TICKET_VALIDATED indique que cette validation s'est bien faite et que le serveur CAS a renvoyé l'identifiant de l'utilisateur à la webapp.

Pour le moment nous en sommes au même stade qu'avant d'avoir configuré le SSL. Maintenant, accédez à la deuxième webapp https://localhost:8443/mywebapp2/, essayez d'accéder à l'espace protégé https://localhost:8443/mywebapp2/protected/ et normalement vous ne devriez pas être redirigé vers la page de login du serveur CAS : l'application vous a automatiquement reconnu. En fait, si vous utilisez un outil tel que httpfox pour analyser ce qui se passe réellement au niveau des trames HTTP, vous observerez qu'une redirection vers le serveur CAS a bien eu lieu, mais que celui-ci vous a instantanément redirigé à son tour vers l'application, ce qui fait que du point de vue de l'utilisateur lambda le processus est transparent.

Première connexion sur Webapp2

Authentification automatique, on accède à l'espace protégé de webapp2 sans avoir besoin d'entrer des identifiants

Logs observés dans la console durant le processus

2013-09-14 19:26:25,818 INFO [org.jasig.cas.CentralAuthenticationServiceImpl] - <Granted service ticket [ST-2-3vWdlNF2v1DXXag7OCIu-cas01.example.org] for service [https://localhost:8443/mywebapp2/protected/] for user [example]>
2013-09-14 19:26:25,818 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: example
WHAT: ST-2-3vWdlNF2v1DXXag7OCIu-cas01.example.org for https://localhost:8443/mywebapp2/protected/
ACTION: SERVICE_TICKET_CREATED
APPLICATION: CAS
WHEN: Sat Sep 14 19:26:25 CEST 2013
CLIENT IP ADDRESS: 0:0:0:0:0:0:0:1
SERVER IP ADDRESS: 0:0:0:0:0:0:0:1
=============================================================

>
2013-09-14 19:26:25,833 INFO [org.jasig.cas.authentication.AuthenticationManagerImpl] - <org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler successfully authenticated [callbackUrl: https://localhost:8443/mywebapp/proxyCallback]>
2013-09-14 19:26:25,833 INFO [org.jasig.cas.authentication.AuthenticationManagerImpl] - <Resolved principal https://localhost:8443/mywebapp/proxyCallback>
2013-09-14 19:26:25,834 INFO [org.jasig.cas.authentication.AuthenticationManagerImpl] - <org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler@ff49ab authenticated https://localhost:8443/mywebapp/proxyCallback with credential [callbackUrl: https://localhost:8443/mywebapp/proxyCallback].>
2013-09-14 19:26:25,834 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: [callbackUrl: https://localhost:8443/mywebapp/proxyCallback]
WHAT: supplied credentials: [callbackUrl: https://localhost:8443/mywebapp/proxyCallback]
ACTION: AUTHENTICATION_SUCCESS
APPLICATION: CAS
WHEN: Sat Sep 14 19:26:25 CEST 2013
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: 127.0.0.1
=============================================================

>
2013-09-14 19:26:25,834 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: example
WHAT: TGT-3-rUGpMtFlGMcjN3OY3TZMQpmPE4boAftlOet9PV4yvegdmdacEy-cas01.example.org
ACTION: PROXY_GRANTING_TICKET_CREATED
APPLICATION: CAS
WHEN: Sat Sep 14 19:26:25 CEST 2013
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: 127.0.0.1
=============================================================

>
2013-09-14 19:26:25,835 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: audit:unknown
WHAT: ST-2-3vWdlNF2v1DXXag7OCIu-cas01.example.org
ACTION: SERVICE_TICKET_VALIDATED
APPLICATION: CAS
WHEN: Sat Sep 14 19:26:25 CEST 2013
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: 127.0.0.1
=============================================================

>
sept. 14, 2013 7:26:25 PM org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl retrieve
INFO: No Proxy Ticket found for [PGTIOU-2-pbTcGbkgEgmi2B6YWO5n-cas01.example.org].

Petit commentaire sur ces logs, vous remarquerez simplement en comparant avec les logs de la première étape que cette fois-ci les étapes correspondant à AUTHENTICATION_SUCCESS et TICKET_GRANTING_TICKET_CREATED ont été sautées, tout simplement parce que le CAS a reconnu l'utilisateur. C'est pour cette même raison qu'il n'affiche pas de formulaire d'authentification et que l'utilisateur ne se rend même pas compte qu'il a été redirigé sur le serveur CAS avant d'accéder à l'espace protégé de webapp2.

IV-E - Exemple de logout

Comme nous l'avons mentionné au III-D, la déconnexion du SSO s'effectue via l'appel de l'URL /cas/logout.

Appel de l'URLde déconnexion du serveur CAS

Logs observés dans la console durant le processus

2013-09-14 20:10:41,452 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: audit:unknown
WHAT: TGT-1-lcyDdbynZWtxpPp6fc7bsQO4Vm0lYKmEbpgp6vL9x6oxFT7qAe-cas01.example.org
ACTION: TICKET_GRANTING_TICKET_DESTROYED
APPLICATION: CAS
WHEN: Sat Sep 14 20:10:41 CEST 2013
CLIENT IP ADDRESS: 0:0:0:0:0:0:0:1
SERVER IP ADDRESS: 0:0:0:0:0:0:0:1
=============================================================

Les logs montrent que le cookie CASTGC a bien été détruit.

V - Débogage

Si vous n'êtes pas familier avec la notion de débogage, je vous invite à consulter mon introduction sur la question. En ce qui concerne le débogage spécifique au SSO CAS, nous sommes dans un cas assez complexe, car il y a d'une part des communications client-serveur par le biais du navigateur du client, et d'autre part des communications de serveur à serveur. Finalement, il vous faudra donc recouper les informations tirées des logs du serveur CAS, celles qui proviennent des logs de l?application, et enfin les traces HTTP observées dans le navigateur. Côté serveur CAS, je vous conseille d'utiliser deux fichiers de logs séparés, l'un pour journaliser toutes les requêtes normales, qu'il s'agisse d'une demande d'authentification d'un client ou d'une demande de validation de ticket d'une application, et l'autre pour tracer l'ensemble des erreurs rencontrées, ceci facilite énormément la vie pour le débogage. Si le besoin s'en fait sentir, un prochain cours viendra détailler cette problématique.

TracesHTTPcorrespondant au test en HTTPS effectué au IV-D

(cliquez ici pour aggrandir l'image)

VI - Pour aller plus loin?

Pour aller plus loin, la première ressource à consulter est le site officiel, jasig.org et en particulier la page sur l'architecture du CAS que nous avons déjà mentionnée, ainsi que le wiki officiel dédié aux clients CAS, et en particulier la page sur l'exemple duquel la première partie de ce tutoriel est inspirée. Vous pouvez aussi vous inscrire aux différentes mailing lists de support. Mais toutes ces ressources sont en anglais.

Côté documentation francophone, je vous recommande en premier lieu les slides de la présentation du CAS faite à Devoxx France 2013 par Jérôme Leleu, qui fait partie des développeurs du CAS. Il y a aussi quelques ressources (voir aussi ici), mises à disposition par le consortium ESUP Portail, ainsi que quelques mailing lists francophones.

Conclusion

Dans ce tutoriel nous avons montré comment mettre en place une maquette de faisabilité du serveur CAS, et expliqué les grands principes. Le serveur qui héberge le CAS fait partie de vos serveurs web, et chaque fois qu'un nouvel utilisateur se connecte à une application, celle-ci le redirige sur le serveur CAS, qui lui présente un formulaire d'authentification s'il ne le reconnaît pas, puis dans tous les cas une fois l'utilisateur connu, redirige celui-ci vers l'application, muni d'un ticket de service. À son tour, l'application se connecte sur le serveur CAS et lui communique le ticket de service de l'utilisateur. Le serveur CAS renvoie alors à son tour à l'application l'identifiant unique de l'utilisateur qui est désormais authentifié. C'est ce mécanisme qui fonde le SSO CAS, et qui permet une authentification unique quel que soit le nombre d'applications visitées.

Ajoutons que nous n'avons évoqué ici que la partie la plus simple du protocole CAS. De fait il existe un mécanisme assez complexe permettant à un service de confiance (proxy) d'effectuer des actions à la place de l'utilisateur (par exemple effectuer des requêtes vers un service tiers qui requiert également une authentification CAS). Nous n'entrerons pas dans les détails, nous vous invitons à consulter la documentation dédiée (en anglais) pour davantage de détails.

Par ailleurs nous n'avons pas évoqué certains paramétrages importants pour obtenir un serveur CAS utilisable en production, à commencer par le paramétrage de la liste des applications web autorisées à y accéder (par défaut toutes le peuvent), ceci afin d'éviter des atteintes à la sécurité de votre annuaire. Enfin, en fonction de la charge envisagée, vous pourrez être amené à mettre en place divers mécanismes de mise en cache et de répartition de charge. Voir ici (en anglais) pour plus d'informations sur ces questions.

Remerciements

Au moment de publier enfin cet article, je voudrais remercier thierryler et keulkeul pour leur relecture technique et leurs encouragements, ClaudeLELOUP pour sa relecture orthographique et ses remarques, ainsi que djibril pour son aide dans l'utilisation des outils de rédaction, et enfin l'ensemble de mes collègues de travail pour leurs conseils et leurs encouragements, en particulier Modou Bane, Mickaël Remond et Jérôme Leleu.

Retour à l'article

Retour à l'article

Retour à l'article