source: spip-zone/_plugins_/authentification/openid/inc/openid.php @ 32151

Last change on this file since 32151 was 32151, checked in by cedric@…, 10 years ago

faire passer l'erreur au form de login

File size: 12.0 KB
Line 
1<?php
2
3@define('_OPENID_LOG', true);
4
5function nettoyer_openid($openid){
6        $openid = vider_url($openid, false);
7        $openid = rtrim($openid,'/');
8        // si pas de protocole et que ca ne semble pas un email style gmail,
9        // mettre http://
10        if ($openid  AND !preg_match(';^[a-z]{3,6}://;i',$openid ) AND strpos($openid,'@')===FALSE)
11                $openid = "http://".$openid;
12
13        // pas d'ancre dans une url openid !
14        $openid = preg_replace(',#[^#]*$,','',$openid);
15
16        return $openid;
17}
18/*****
19 * Initialisation de l'authent OpenID
20 ****/
21
22function init_auth_openid() {
23        session_start();
24       
25        $cwd = getcwd();
26        //chdir(dirname(dirname(__FILE__)));
27        chdir(realpath(_DIR_OPENID_LIB));
28        require_once "Auth/OpenID/Consumer.php";
29        require_once "Auth/OpenID/FileStore.php";
30    require_once "Auth/OpenID/SReg.php"; // Require the Simple Registration extension API.
31        chdir($cwd);
32
33        /****
34         * Répertoire temporaire où auth_openid stocke ses données
35         * afin de suivre les sessions.
36         ****/
37
38        $store = new Auth_OpenID_FileStore(sous_repertoire(_DIR_TMP, 'auth_openid'));
39
40        /**
41         * Create a consumer object using the store object created earlier.
42         */
43        return new Auth_OpenID_Consumer($store);
44}
45
46
47/**
48 * Logs pour openID, avec plusieurs niveaux pour le debug (1 a 3)
49 *
50 * @param mixed $data : contenu du log
51 * @param int(1) $niveau : niveau de complexite du log
52 * @return null
53**/
54function openid_log($data, $niveau=1){
55        if (!defined('_OPENID_LOG') OR _OPENID_LOG < $niveau) return;
56        spip_log('OpenID: '.$data, 'openid');
57}
58
59
60
61function demander_authentification_openid($login, $cible){
62        openid_log("Traitement login OpenID pour $login",2);
63
64        // Begin the OpenID authentication process.
65        $consumer = init_auth_openid();
66        openid_log("Initialisation faite", 3);
67        $auth_request = $consumer->begin($login);
68
69        // Handle failure status return values.
70        if (!$auth_request) {
71                // ici, on peut rentrer dire que l'openid n'est pas connu...
72                // plutot que de rediriger et passer la main a d'autres methodes d'auth
73                openid_log("Ce login ($login) n'est pas connu", 2);
74                return _T('openid:erreur_openid');
75        } 
76       
77        // l'openid donne est connu. On va donc envoyer une redirection
78        // mais celle ci est differente selon la version de openid
79        //
80        // Dans les 2 cas, deux parametres doivent etre donnes
81        // - une url de confiance, ici l'adresse du site : url_de_base()
82        // - une url de redirection, sur laquelle OPENID reviendra une fois l'authentification faite (réussie ou non)
83        else {
84                openid_log("Le login $login existe", 2);
85                // argument de redirection : cette url doit etre identique
86                // ici et au retour (au moins le premier parametre de l'url)
87                // sinon le script openid n'est pas content
88                // On peut neanmoins passer des informations supplementaires
89                // nous indiquons ici une autre redirection encore, celle de l'url
90                // vers laquelle le bonhomme souhaite aller (url=$cible)
91               
92                // attention, il ne faut pas utiliser parametre_url() afin
93                // d'encoder $cible, ce qui casserait la transaction...
94                $retour = parametre_url(openid_url_reception(), "url", url_absolue($cible), '&');
95                openid_log("Adresse de retour : $retour", 2);
96                // on demande quelques informations, dont le login obligatoire
97                if ($sreg_request = Auth_OpenID_SRegRequest::build(
98                                array('nickname'), // Required
99                                array('fullname', 'email')) // Optional
100                ) {
101                        openid_log("Ajout des extensions demandees", 3);
102                $auth_request->addExtension($sreg_request);
103                }
104
105                $erreur = "";
106               
107                // OPENID 1
108                if ($auth_request->shouldSendRedirect()) {
109                        openid_log("Redirection pour version 1 d'OpenID", 3);
110                        // Redirect the user to the OpenID server for authentication.  Store
111                        // the token for this authentication so we can verify the response.
112                        $redirect = $auth_request->redirectURL(url_de_base(), $retour);         
113                        openid_log("Redirection vers : $redirect", 3);
114                       
115                        // If the redirect URL can't be built, display an error message.
116                        if (Auth_OpenID::isFailure($redirect)) {
117                                openid_log("Erreur sur l'adresse de redirection : $redirect", 2);
118                                $erreur = openid_url_erreur(_L("Could not redirect to server: " . $redirect->message), $cible);
119                        }
120                }
121               
122                // OPENID 2
123                // use a Javascript form to send a POST request to the server.
124                else {
125                        openid_log("Redirection pour version 2 d'OpenID", 3);
126                        // Generate form markup and render it.
127                        $form_id = 'openid_message';
128                        $form_html = $auth_request->formMarkup(url_de_base(), $retour, false, array('id' => $form_id));
129                        openid_log("Redirection par formulaire : $form_html", 3);
130                        // Display an error if the form markup couldn't be generated;
131                        // otherwise, render the HTML.
132                        if (Auth_OpenID::isFailure($form_html)) {
133                                openid_log("Erreur sur le formulaire de redirection : $form_html", 2);
134                                $erreur = openid_url_erreur(_L("Could not redirect to server: " . $form_html->message), $cible);
135                        } 
136                       
137                        // pas d'erreur : affichage du formulaire et arret du script
138                        else {
139                                openid_log("Affichage du formulaire de redirection", 3);
140                                $page_contents = array(
141                                   "<html><head><title>",
142                                   "OpenID transaction in progress",
143                                   "</title></head>",
144                                   "<body onload='document.getElementById(\"".$form_id."\").submit()'>",
145                                   $form_html,
146                                   "</body></html>");
147                                echo implode("\n", $page_contents);
148                                exit;
149                        }
150                }
151
152        }       
153       
154        if ($erreur) {
155                openid_log("Rentrer avec l'erreur", 3);
156                return $erreur;
157        }
158       
159        openid_log("Redirection par entete", 3);
160        include_spip('inc/headers');
161        #redirige_par_entete($redirect);               
162        echo redirige_formulaire($redirect);
163        exit;
164}
165
166
167
168// analyse le retour de la requete openID
169// et redirige vers une url en fonction
170function terminer_authentification_openid($cible){
171        $redirect=""; // redirection sur erreur
172        openid_log("Retour du fournisseur OpenId avec : $cible", 2);
173       
174        // Complete the authentication process using the server's response.
175        $consumer = init_auth_openid();
176        openid_log("Initialisation faite. analyse de la reponse rendue", 2);
177        $response = $consumer->complete(openid_url_reception());
178
179        // This means the authentication was cancelled.
180        if ($response->status == Auth_OpenID_CANCEL) {
181                openid_log("Processus annule par l'utilisateur", 2);
182            $redirect = openid_url_erreur(_T('openid:verif_refusee'), $cible); 
183        } 
184       
185        // Authentification echouee
186        elseif ($response->status == Auth_OpenID_FAILURE) {
187                openid_log("Echec de l'authentification chez le fournisseur", 2);
188            $redirect = openid_url_erreur("Authentication failed: " . $response->message, $cible);
189        } 
190       
191        // This means the authentication succeeded.
192        elseif ($response->status == Auth_OpenID_SUCCESS) {
193               
194                $openid = nettoyer_openid($response->identity_url); // pas de / final dans l'openid
195               
196                $esc_identity = htmlspecialchars($openid, ENT_QUOTES);
197                openid_log("Succes de l'authentification $openid chez le fournisseur d'identification", 1);
198
199                // identification dans SPIP
200                // (charge inc/auth_openid)
201                openid_log("Verification de l'identite '$openid' dans SPIP", 2);
202
203                $auth = charger_fonction('openid','auth');
204                if (!$ok = $auteur = $auth($openid, "","","",'ok')){ // pas de mot de passe
205                        // c'est ici que l'on peut ajouter un utilisateur inconnu dans SPIP
206                        // en plus, on connait (si la personne l'a autorise) son nom et email
207                        // en plus du login
208                        openid_log("Identite '$openid' inconnue SPIP", 2);
209                       
210                        // recuperer login, nom, email
211                        $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($response);
212                        $sreg = $sreg_resp->contents();
213                        $couples = array(
214                                'login' => isset($sreg['nickname']) ? $sreg['nickname'] : '',
215                                'email' => isset($sreg['email']) ? $sreg['email'] : '', 
216                                // login a defaut du nom, sinon c'est 'Nouvel auteur' qui est enregistre
217                                'nom' => isset($sreg['fullname']) ? $sreg['fullname'] : $sreg['nickname'],
218                                'openid' => $openid
219                        );
220
221                        #openid_log("sreg ".var_export($sreg_resp,true), 2);
222
223                        // on ajoute un auteur uniquement si les inscriptions sont autorisees sur le site
224                        if ($GLOBALS['meta']['accepter_inscriptions']=='oui') {
225                               
226                                openid_log("Tenter d'ajouter '$openid' dans SPIP");
227                                // verifier qu'on a les infos necessaires
228                                if (!$ok = ($couples['login'] AND $couples['email'])) {
229                                        openid_log("Les informations transmises ne sont pas suffisantes : il manque le login et/ou l'email pour $openid.");
230                                        $redirect = openid_url_erreur(_L("Inscription impossible : login ou email non renvoy&eacute;"), $cible);
231                                }
232                                // ajouter l'auteur si le login propose n'existe pas deja
233                                elseif (!$ok = openid_ajouter_auteur($couples)) {
234                                        openid_log("Inscription impossible de '$openid' car un login ($couples[login]) existe deja dans SPIP");
235                                        $redirect = openid_url_erreur(_L("Inscription impossible : un login identique existe deja"), $cible);
236                                } 
237                                // verifier que l'insertion s'est bien deroulee
238                                else {
239                                        if (($ok = $identifier_login($openid, "")) && $cible){                                 
240                                                openid_log("Inscription de '$openid' dans SPIP OK", 3);
241                                                $cible = parametre_url($cible,'message_ok',_L('openid:Vous &ecirc;tes maintenant inscrit et identifi&eacute; sur le site. Merci.'),'&');
242                                        } else {
243                                                openid_log("Echec de l'ajout de '$openid' dans SPIP", 3);
244                                        }
245                                }
246                        }
247                        // rediriger si pas inscrit
248                        if (!$ok && !$redirect) {
249                                $redirect = openid_url_erreur(_L("Utilisateur OpenID inconnu dans le site)"), $cible);
250                        }
251                }
252               
253                // sinon, c'est on est habilite ;)
254                if ($ok) {
255                        openid_log("Utilisateur '$openid' connu dans SPIP, on l'authentifie", 3);
256                       
257                        // creer la session
258                                $session = charger_fonction('session', 'inc');
259                                $session($auteur);
260                                $p = ($auteur['prefs']) ? unserialize($auteur['prefs']) : array();
261                                $p['cnx'] = ($session_remember == 'oui') ? 'perma' : '';
262                                $p = array('prefs' => serialize($p));
263                                sql_updateq('spip_auteurs', $p, "id_auteur=" . $auteur['id_auteur']);
264                                //  bloquer ici le visiteur qui tente d'abuser de ses droits
265                                verifier_visiteur();                   
266                       
267                        ## Cette partie est identique
268                        ## a formulaire_login_traiter
269                        #$auth = charger_fonction('auth','inc');
270                        #$auth();
271
272                        // Si on se connecte dans l'espace prive,
273                        // ajouter "bonjour" (repere a peu pres les cookies desactives)
274                        if (openid_is_url_prive($cible)) {
275                                $cible = parametre_url($cible, 'bonjour', 'oui', '&');
276                        }
277                        if ($cible) {
278                                $cible = parametre_url($cible, 'var_login', '', '&');
279                        } 
280                       
281                        // transformer la cible absolue en cible relative
282                        // pour pas echouer quand la meta adresse_site est foireuse
283                        if (strncmp($cible,$u = url_de_base(),strlen($u))==0){
284                                $cible = "./".substr($cible,strlen($u));
285                        }
286               
287                        // Si on est admin, poser le cookie de correspondance
288                        if ($GLOBALS['auteur_session']['statut'] == '0minirezo') {
289                                include_spip('inc/cookie');
290                                spip_setcookie('spip_admin', '@'.$GLOBALS['auteur_session']['login'],
291                                time() + 7 * 24 * 3600);
292                        }
293                        ## /fin identique
294                }
295        }
296       
297        include_spip('inc/headers');
298        redirige_par_entete($redirect?$redirect:$cible);       
299}
300
301
302function openid_url_reception(){
303        include_spip('inc/filtres');
304        return url_absolue(generer_url_action("controler_openid"));
305}
306
307function openid_url_erreur($message, $cible=''){
308        openid_log($message);
309        if ($cible)
310                $ret = $cible;
311        else
312                $ret = generer_url_public("login","url=".$redirect,'&'); // $redirect pas defini ici ..
313        return parametre_url($ret, "var_erreur", urlencode($message),'&');
314}
315
316function openid_is_url_prive($cible){
317        $parse = parse_url($cible);
318        return strncmp(substr($parse['path'],-strlen(_DIR_RESTREINT_ABS)), _DIR_RESTREINT_ABS, strlen(_DIR_RESTREINT_ABS))==0; 
319}
320
321function openid_ajouter_auteur($couples){
322        $statut = ($GLOBALS['openid_statut_nouvel_auteur'] 
323                        ? $GLOBALS['openid_statut_nouvel_auteur'] 
324                        : '1comite');
325                       
326        include_spip('base/abstract_sql');
327        // si un utilisateur possede le meme login, on ne continue pas
328        // sinon on risque de perdre l'integrite de la table
329        // (pour le moment, on suppose dans la table spip_auteurs
330        // qu'un login ou qu'un opentid est unique)
331        if (sql_getfetsel('id_auteur','spip_auteurs','login='.sql_quote($couples['login']))) {
332                return false;
333        }
334        $id_auteur = sql_insertq("spip_auteurs", array('statut' => $statut));
335        openid_log("Creation de l'auteur '$id_auteur' pour $couples[login]", 3);
336        include_spip('inc/modifier');
337        revision_auteur($id_auteur, $couples);
338       
339        return true;
340}
341
342?>
Note: See TracBrowser for help on using the repository browser.