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

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

faire et defaire ! on remet a la racine tout ce qui peut etre commun entre les 2 versions du plugin
et on commence a faire le portage 2.1

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