source: spip-zone/_plugins_/simplesaml/trunk/auth/simplesaml.php @ 93428

Last change on this file since 93428 was 93428, checked in by marcimat@…, 4 years ago

Ajout d'un plugin pour s'interfacer avec un fournisseur d'identité SAML.
Le plugin utilise ici Simple SAML PHP. Son installation nécessite des
modifications sur le vhost Apache, ainsi qu'une configuration manuelle.

Une explication est fournie sur la page exec=configurer_simplesaml.
Une configuration minimale d'exemple est indiquée dans le répertoire
simplesaml-config-exemple.

Un auteur SPIP 6forum (de source d'identification 'saml')
est créé lors d'une identification valide, en récupérant
le nom, prénom, email.

Ce plugin ne fournit pas (actuellement) une authentification
supplémentaire dans le formulaire de login habituel. Pour l'instant,
dans l'utilisation qu'on en a, notre spip, sur un domaine,
se loge sur un autre sous-domaine du même domaine, via SAML.
La balise #URL_LOGIN_SIMPLESAML retourne l'url de connexion
si la personne n'est pas déjà identifiée. #URL_LOGOUT (habituelle)
permet de se déconnecter, du SPIP et du SSO.

Si la personne est déjà identifiée sur le SSO, mais pas directement
sur le SPIP (c'est à dire qu'elle s'est authentifiée sur un autre
sous domaine), on peut faire en sorte de se connecter automatiquement,
en lisant un cookie global au domaine qui indique l'état de connexion
au SSO. Cette possibilité, le nom du cookie, et sa valeur se déclare
dans le formulaire de configuration. (Je n'ai pas encore pu vérifier
le bon fonctionnement, mais ça ne saurait tarder !)

Ce plugin est une refonte totale d'un plugin SPiP créé par Entrouvert,
à l'origine pour SPIP 1.9.2 et modifié au fur et à mesure jusqu'en 3.0.
Merci à eux :)

Notons que le plugin ne permet pas, en l'état non plus, de faire en sorte
que SPIP soit un fournisseur d'identité. Il permet juste d'être fournisseur
de service. Mais l'étendre à cette possibilité serait sympa toutefois.

File size: 4.6 KB
Line 
1<?php
2/**
3 * Fichier gérant l'installation et désinstallation du plugin Authentification SAML
4 *
5 * @plugin     Authentification SAML
6 * @copyright  2015
7 * @author     Matthieu Marcillaud
8 * @licence    GNU/GPL
9 * @package    SPIP\SimpleSaml\Authentification
10 */
11
12if (!defined('_ECRIRE_INC_VERSION')) return;
13
14
15
16/**
17 * Identifie dans SPIP l'auteur connecté par SAML
18 *
19 * @param \SimpleSAML_Auth_Simple $simplesaml
20 * @return bool
21 *     True si réussi, false sinon.
22**/
23function simplesaml_auth_loger(\SimpleSAML_Auth_Simple $simplesaml) {
24
25        $simplesaml = new SimpleSAML_Auth_Simple('default-sp');
26        if (!$simplesaml->isAuthenticated()) {
27                return false;
28        }
29
30        $nameid     = $simplesaml->getAuthData('saml:sp:NameID');
31        $nameid     = $nameid['Value'];
32
33        $attributes = $simplesaml->getAttributes();
34        $login      = $attributes['uid'][0];
35        $prenom     = $attributes['gn'][0];
36        $nom        = $attributes['sn'][0];
37        $email      = $attributes['email'][0];
38
39        if ($prenom) {
40                $nom = $prenom . ' ' . $nom;
41        }
42
43        if (!$nameid) {
44                spip_log("No NameID found in SAML data, cancel login", 'simplesaml.' . _LOG_ERREUR);
45                return false;
46        }
47
48        spip_log("Authentification reussi pour l'utilisateur = " . $email, 'simplesaml');
49
50        // chercher notre auteur, s'il existe.
51        // nameid
52        $auteur = sql_fetsel('*', 'spip_auteurs', array(
53                'source = ' . sql_quote('saml'),
54                'statut != ' . sql_quote('5poubelle'),
55                'nameid = ' . sql_quote($nameid)
56        ));
57
58        // sinon uid.
59        if (!$auteur) {
60                $auteur = sql_fetsel('*', 'spip_auteurs', array(
61                        'source = ' . sql_quote('saml'),
62                        'statut != ' . sql_quote('5poubelle'),
63                        'login = ' . sql_quote($login)
64                ));
65        }
66
67        include_spip('action/editer_auteur');
68        if (!$auteur) {
69                $id_auteur = auteur_inserer('saml', array(
70                        'login'   => $login,
71                        'statut'  => '6forum',
72                        'nameid'  => $nameid,
73                        'nom'     => $nom,
74                        'email'   => $email
75                ));
76                if (!$id_auteur) {
77                        spip_log('impossible de créer le nouvel auteur spip', 'simplesaml');
78                        return false;
79                }
80        } else {
81                $id_auteur = $auteur['id_auteur'];
82                // mettre à jour ses données
83                sql_updateq(
84                        'spip_auteurs',
85                        array(
86                                'login'   => $login,
87                                'nameid'  => $nameid,
88                                'nom'     => $nom,
89                                'email'   => $email
90                        ),
91                        'id_auteur = ' . $id_auteur
92                );
93        }
94
95        $auteur = sql_fetsel('*', 'spip_auteurs', 'id_auteur=' . $id_auteur);
96        include_spip('inc/auth');
97        return auth_loger($auteur);
98}
99
100
101
102/**
103 * Vider les sessions de l'auteur connecté
104**/
105function simplesaml_vider_sessions() {
106        // le logout explicite vaut destruction de toutes les sessions
107        if (isset($_COOKIE['spip_session'])) {
108                include_spip('inc/cookie');
109                $session = charger_fonction('session', 'inc');
110                $session($GLOBALS['visiteur_session']['id_auteur']);
111                spip_setcookie('spip_session', $_COOKIE['spip_session'], time()-3600);
112        }
113}
114
115
116/**
117 * Si une authentification a déjà été réalisée sur un autre sous-domaine de ce domaine,
118 * on va se loger automatiquement sur le fournisseur d'identité.
119 *
120 * Pour savoir si c'est le cas, on teste la présence d'un cookie, cookie qui doit
121 * s'appliquer sur tout le domaine, tel que '.domaine.tld'
122 *
123 * Le nom et la valeur du cookie sont à définir en configuration.
124 *
125 * @param string $url URL de retour
126 * @return bool
127 *     True si réussi, false sinon.
128**/
129function simplesaml_auth_autologer() {
130        include_spip('lire_config');
131        if (lire_config('simplesaml/autologer/activer')) {
132                $simplesaml = new SimpleSAML_Auth_Simple('default-sp');
133                if (!$simplesaml->isAuthenticated()) {
134                        $cookie = lire_config('simplesaml/autologer/cookie/nom');
135                        $valeur = lire_config('simplesaml/autologer/cookie/valeur');
136                        if (isset($_COOKIE[$cookie]) and ($_COOKIE[$cookie] == $valeur)) {
137                                // a priori on est identifié sur le même domaine quelque part.
138                                $simplesaml->requireAuth();
139                        }
140                }
141        }
142}
143
144
145/**
146 * Déloge du SSO si on y est authentifié
147 *
148 * Provoque une redirection vers le SSO pour ça si besoin
149 *
150 * @param string $url URL de retour
151**/
152function simplesaml_auth_deloger($url) {
153        $simplesaml = new SimpleSAML_Auth_Simple('default-sp');
154        if ($simplesaml->isAuthenticated()) {
155                simplesaml_vider_sessions();
156                $simplesaml->logout(url_absolue($url));
157                // normalement… ça doit rediriger
158        }
159}
160
161
162/**
163 * Déloge de SPIP un auteur s'il n'est plus connecté au SSO
164 *
165 * @param string $url URL de retour
166**/
167function simplesaml_auth_deloger_spip_si_besoin($url) {
168        $simplesaml = new SimpleSAML_Auth_Simple('default-sp');
169        if (!$simplesaml->isAuthenticated()) {
170                // aucasou on serait effectivement logé ailleurs sur le SSO
171                simplesaml_auth_autologer();
172
173                // sinon, tuer notre session SPIP
174                simplesaml_vider_sessions();
175                include_spip('inc/headers');
176                redirige_par_entete(self());
177        }
178}
Note: See TracBrowser for help on using the repository browser.