Spip Ô Toulouse
Accueil du site > Ateliers > Aides et astuces > SPIP-Comment être authentifié automatiquement dans l’espace privé

SSO SPIPOTOULOUSE

SPIP-Comment être authentifié automatiquement dans l’espace privé

vendredi 14 novembre 2008, par Yoann Nogues

Lorsque l’on a plusieurs applications dans un système d’information, il est fortement utile de n’avoir qu’un seul identifiant et mot de passe et de passer de manière transparente d’une application à l’autre sans avoir à ressaisir le mot de passe. Cet intérêt est un gain de temps, limiter la complexité des différentes applications et surtout faciliter la vie de l’utilisateur.

Le terme SSO, signifie (en gros) une seule authentification pour un même système d’information.

Préambule

- Avoir au moins 2 applications ( SPIP + une autre dans mon cas Portaneo )
- Ces 2 applications sont disponibles sur 2 noms de domaines différents
- Me simplifier la tache les 2 applications sont développées en PHP

Mode de fonctionnement souhaité

Je suis identifié dans mon application Portaneo ( c’est un portail a la igoogle ou netvibes ). Je fais donc remonter des flux RSS de SPIP dans cette application.

Dans ce portail, j’ai un lien vers l’espace privé de SPIP qui me permet de proposer un nouvel article. Je dois donc être "connecté en tant que rédacteur" à minima.

Comment fonctionne l’authentification de SPIP ?

Le script qui vérifie l’authentification de SPIP à proprement parler est dans ecrire/inc/auth.php. Ce script fait appel aux différentes méthodes inc/auth_spip.php (authentification standard de SPIP), et inc/auth_ldap.php (authentification via ldap et ajout de l’utilisateur dans la table spip_auteurs lors de la première connection).
inc/auth_spip et inc/auth_ldap ont une fonction (la principale) qui retourne un tableau contenant un utilisateur si l’authentification a réussie.

Il y a 1 seul appel a inc/auth.php : dans ecrire/index.php qui va juste tester si on est toujours connecté ( afin de valider l’affichage des pages de l’espace privé. Dans ce cas je ne parle que de l’affichage des pages du type ecrire/ ?exec=xxxxx.

inc/auth.php n’est pas le fichier/méthode appellé(e) lors de la "mise en mémoire" de votre authentification. Cette mise en mémoire se fait par l’intermédiaire d’un cookie qui est placé sur le poste client. En fait c’est plutôt 3 cookies, mais on ne va pas détailler :)

Si on regarde la dernière étape de la validation du formulaire de login, on s’aperçoit qu’elle renvoie vers le fichier ecrire/action/cookie.php. Et c’est dans celui-ci que l’on va mettre en place le cookie de session (après vérification de l’authentification). Ce fichier va appeler consécutivement les 2 méthodes d’authentification (spip puis ldap), via le code suivant :

// Essayer l'authentification par MySQL
        $auth_spip = charger_fonction('auth_spip', 'inc', true);
        if ($auth_spip) $row_auteur = $auth_spip($session_login, $session_password);
//.........


// Marche pas: essayer l'authentification par LDAP si present
if (!$row_auteur AND $GLOBALS['ldap_present']) {
        $auth_ldap = charger_fonction('auth_ldap', 'inc', true);
        if ($auth_ldap) $row_auteur = $auth_ldap($session_login, $session_password);
        }

Si un de ces 2 bouts de code retourne une table d’auteur ($row_auteur), alors on lance le processus d’enregistrement des cookies et de la session.

Il est donc suffisant d’avoir un $row_auteur à ce niveau pour valider l’authentification et pouvoir accéder à l’espace, etc ...

Quand SPIP vous considère comme connecté ?

C’est la première mécanique que j’ai énoncé. C’est inc/auth.php et qui est appelé dans ecrire/index.php (notamment pour accéder a l’espace privé).

Ce fichier vérifie la présence du cookie de session sinon il teste l’authentification HTTP et transforme la session existante en variables globales. Si on est pas connecté, inc_auth_dist() renverra la chaine "inconnu" ou -1. Dans le cas inverse (connecté), cela enregistre dans des variables globales certaines choses ( les rubriques autorisées, l’identifiant de l’auteur, son login par exemple). Ces informations mises en "global" sont contenues dans le fichier de session que l’on peut trouver dans le serveur dans le répertoire tmp/sessions/spip_XX_YYYYYYYYYYYYY.php, ou XX est l’identifiant de l’auteur et YYYYYY une chaine aléatoire (pour ne pas rentrer dans le détail :p).

Comment faire alors pour être considéré comme connecté dans SPIP ?

La méthode qui m’a parue la plus simple et la plus sure est de rajouter un système d’authentification. Il s’agit donc d’intervenir dans le fichier action/cookie, ainsi que rajouter le rajouter le fichier inc/auth_sso.php.

Zip - 629 octets
inc/auth_sso.php
C’est le fichier (trés simple) qui permet de rajouter une méthode d’authentification dans SPIP

Rajouter une autre méthode d’authentification dans SPIP

Il convient donc pour éviter de faire trop sale de rajouter un fichier dans squelettes/inc/auth_sso.php. Un exemple de ce fichier est en pièce jointe de l’article.

Il faut ensuite faire appel à cette méthode d’authentification dans le fichier action/cookie.php et ce après l’appel de auth_spip.

Donc après :

        // Essayer l'authentification par MySQL
        $auth_spip = charger_fonction('auth_spip', 'inc', true);
        if ($auth_spip) $row_auteur = $auth_spip($session_login, $session_password);

il faut avoir cela :

if (!$row_auteur && $auth_hash){
  $auth_sso = charger_fonction('auth_sso', 'inc', true);
  $row_auteur=$auth_sso ($auth_hash);
  $session_login=$row_auteur['login'];
}

Ce qu’implique techniquement une autre authentification de SPIP ?

Dans la solution que je préconise, on va rajouter un champ "auth_hash" en varchar 255 , dans la table spip_auteurs de SPIP.

Ce champ sera rempli par votre autre application. Voici un petit exemple de ce à quoi ça pourrait ressembler (dans l’application Portaneo) :

//définition du HASH et inscription dans table SPIP

 $DB_spip = new connection("localhost","maloginspip","monpass","mabasespip");

 $auth_hash=md5(time().$_SESSION['user_id'].$_SESSION['username']);

 $query="update spip_auteurs set auth_hash='".$auth_hash."' where login='".$_SESSION['username']."' limit 1";

 $DB_spip->execute($query);

 $DB_spip->close();

Dans mon cas, je considère qu’un utilisateur sous Portaneo possède le même login ( ou username ) que dans SPIP. C’est le lien que je fais.

On ne peut pas passer uniquement ce login en paramètre à notre système d’authentification de SPIP ... ce serait un peu trop facile. C’est pour cela que l’on va utiliser la variable auth_hash.

Cette variable NE DOIT PAS être permanente, elle doit être supprimée de la table spip_auteurs au bout d’un certain temps, et notamment lors de la déconnexion de votre autre application.

Pour la suppression au bout d’un certain temps, j’ai un cron système qui appelle un script PHP ( car le trafic sur le site SPIP n’est pas suffisant vis à vis de la sécurité, et que je suis sur un hébergement dédié qui me permet de le faire ) ... mais la meilleure solution serait d’utiliser un cron SPIP (dans un cas général, et aussi parce que beaucoup d’entre vous sont sur des hébergements mutualisés).

Je vous laisse le soin de vous faire votre propre "update" à votre "sauce". Pour avoir un exemple de cron SPIP, vous pouvez regarder le code du plugin speed syndic sur la zone

En ce qui concerne la génération de votre md5 auth_hash, vous pouvez utiliser ce que vous voulez... Il suffit juste que ce soit quelque chose de suffisamment sécurisé :)

Comment appeler l’authentification de SPIP ?

Il s’agit donc dans ce cas la de faire un lien vers

http://www.mondomaine.fr/spip.php?action=cookie&auth_hash=YYYYYYY

Si on se contente de cela, on est considéré comme connecté le temps de la session, et donc si à partir d’une autre page fait un lien vers l’espace privé, alors SPIP nous dirigera directement vers cette page.

Par contre, si on veut faire un lien de votre application vers une page de l’espace privé en passant d’abord par l’authentification SPIP, voici un exemple de lien :

http://www.mondomaine.fr/spip.php?action=cookie&auth_hash=YYYYYYY&url=ecrire/?exec=ZZZZZZZ

Dans votre autre appli, comment lancer cette authentification

Dans le portail Portaneo, il y a des templates qui ne sont utilisés que quand je suis connecté. Vu qu’il n’y a pas de cache sur ces templates je peux alors coller mon code qui va me permettre d’être connecté.

Le principe c’est d’avoir une IFRAME dans ce template, et la source de cette IFRAME doit être la page

http://www.monspip.fr/spip.php?action=cookie&auth_hash=xxxxxxxxxxxxxxxxxx

Vous pouvez constater que je n’ai pas rajouter le paramètre "&url=" car en fait je n’en ai pas besoin ... Je ne vais pas visualiser cette page.

Afin d’avoir un fonctionnement plus "sympa" j’ai tenté d’avoir un appel AJAX de cette page, mais les limitations "Cross Domains" m’en ont empêché.

Ce hash correspond à un ticket que Portaneo donne à l’utilisateur pour pouvoir changer d’application.

Pour finir

Vous pouvez maintenant, faire des liens dans votre application directement vers l’espace privé de SPIP :)
Si vous avez des soucis n’hésitez pas à déposer un message dans le forum ci-dessous ou mieux encore sur la liste de spip-zone

Petites erreurs à ne pas faire

Ce paramètre auth_hash ne doit pas s’appeler "hash" car spip utilise déjà cette variable et cela pourrait entrainer des dysfonctionnements.

L’appel de la page pour s’authentifier ne doit pas être

http://www.monspip.fr/ecrire/?action=cookie&auth_hash=xxxxxxxxxxxxxxxxxx

car il y a un processus dans ecrire/index.php qui dira que vous n’êtes pas connecté ... et en gros ça ne correspond pas au fonctionnement souhaité.

P.-S.

Merci encore à Stéphane Laurent pour l’aide sur la liste, ainsi qu’à Pablo Soler et Pierre Fiches pour leurs avis quant à la rédaction de cet article.

3 Messages de forum

Répondre à cet article

SPIP | squelette | | Plan du site | Suivre la vie du site RSS 2.0