Subversion Repositories Applications.wikini

Rev

Rev 66 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
63 aurelien 1
<?php
66 aurelien 2
 
3
// Remplacement de apache_request_headers pour les vieux serveurs
4
// http://stackoverflow.com/questions/2916232/call-to-undefined-function-apache-request-headers
5
if(!function_exists('apache_request_headers')) {
6
        function apache_request_headers() {
7
                // Based on: http://www.iana.org/assignments/message-headers/message-headers.xml#perm-headers
8
                $arrCasedHeaders = array(
9
                                // HTTP
10
                                'Dasl'             => 'DASL',
11
                                'Dav'              => 'DAV',
12
                                'Etag'             => 'ETag',
13
                                'Mime-Version'     => 'MIME-Version',
14
                                'Slug'             => 'SLUG',
15
                                'Te'               => 'TE',
16
                                'Www-Authenticate' => 'WWW-Authenticate',
17
                                // MIME
18
                                'Content-Md5'      => 'Content-MD5',
19
                                'Content-Id'       => 'Content-ID',
20
                                'Content-Features' => 'Content-features',
21
                );
22
                $arrHttpHeaders = array();
23
 
24
                foreach($_SERVER as $strKey => $mixValue) {
25
                        if('HTTP_' !== substr($strKey, 0, 5)) {
26
                                continue;
27
                        }
28
 
29
                        $strHeaderKey = strtolower(substr($strKey, 5));
30
 
31
                        if(0 < substr_count($strHeaderKey, '_')) {
32
                                $arrHeaderKey = explode('_', $strHeaderKey);
33
                                $arrHeaderKey = array_map('ucfirst', $arrHeaderKey);
34
                                $strHeaderKey = implode('-', $arrHeaderKey);
35
                        }
36
                        else {
37
                                $strHeaderKey = ucfirst($strHeaderKey);
38
                        }
39
 
40
                        if(array_key_exists($strHeaderKey, $arrCasedHeaders)) {
41
                                $strHeaderKey = $arrCasedHeaders[$strHeaderKey];
42
                        }
43
 
44
                        $arrHttpHeaders[$strHeaderKey] = $mixValue;
45
                }
46
                return $arrHttpHeaders;
47
        }
48
}
49
 
63 aurelien 50
class identificationSso {
51
 
52
        private $wiki = null;
53
        private $config = null;
54
 
55
        private $cookie_tentative_identification = "";
56
        private $delai_tentative_identification = 60;
65 aurelien 57
 
58
        private $auth_header = 'Authorization';
63 aurelien 59
 
60
        public function __construct($wiki) {
61
                $this->wiki = $wiki;
62
                $this->config = $wiki->config;
65 aurelien 63
                $this->auth_header = !empty($this->config['sso_auth_header']) ? $this->config['sso_auth_header'] : $this->auth_header;
63 aurelien 64
                $this->cookie_tentative_identification = 'wikini_sso_tentative_identification';
65
        }
66
 
67
        function getToken() {
68
                // Premier essai, dans le header
69
                $headers = @apache_request_headers();
70
                $token = !empty($headers['Authorization']) ? $headers['Authorization'] : null;
65 aurelien 71
                // Eventuellement, le jeton a pu être passé dans un header non standard, comme dans 
72
                // le cas où le header Authorization est supprimé par le mod cgi d'apache
73
                // Dans ce cas là on vérifie aussi dans un header alternatif si celui ci a été renseigné
74
                if($token == null && $this->auth_header != 'Authorization') {
75
                        $token = !empty($headers[$this->auth_header]) ? $headers[$this->auth_header] : null;
76
                }
63 aurelien 77
 
78
                // Sinon dans $_REQUEST ?
79
                if($token == null) {
80
                        $token = !empty($_REQUEST['Authorization']) ? $_REQUEST['Authorization'] : null;
81
                }
82
 
83
                // Sinon dans $_COOKIE ?
84
                if($token == null) {
85
                        $token = !empty($_COOKIE['tb_auth']) ? $_COOKIE['tb_auth'] : null;
86
                }
87
 
88
                return $token;
89
        }
90
 
91
        function decoderToken($token) {
92
                $token_parts = explode('.', $token);
93
                return json_decode(base64_decode($token_parts[1]), true);
94
        }
95
 
96
        function getPage() {
97
                return !empty($this->wiki->page) ? $this->wiki->page['tag'] : 'PagePrincipale';
98
        }
99
 
100
        // http://stackoverflow.com/questions/1251582/beautiful-way-to-remove-get-variables-with-php?lq=1
101
        function supprimerUrlVar($url, $var) {
102
                 return rtrim(preg_replace('/([?&])'.$var.'=[^&]+(&|$)/','$1',$url), '&?');
103
        }
104
 
105
        function getInfosCookie() {
106
                $infos = null;
107
                if(!empty($_COOKIE[$this->cookie_tentative_identification])) {
108
                        $infos = json_decode($_COOKIE[$this->cookie_tentative_identification], true);
109
                }
110
                return $infos;
111
        }
112
 
113
        function setInfosCookie($infos) {
114
                $infos['expire'] = !empty($infos['expire']) ? $infos['expire'] : 0;
115
                setcookie($this->cookie_tentative_identification, json_encode($infos), $infos['expire'], $this->wiki->CookiePath);
116
        }
117
 
118
        function verifierEtInsererUtilisateurParJeton($jeton_rafraichi) {
119
                if(!empty($jeton_rafraichi['session']) && $jeton_rafraichi['session'] == true) {
120
                        $token_decode = $this->decoderToken($jeton_rafraichi['token']);
121
 
122
                        $nom_wiki = $token_decode['nomWiki'];
123
                        $courriel = $token_decode['sub'];
124
 
125
                        $utilisateur_wiki_existe = $this->wiki->LoadAll("SELECT * FROM  ".$this->wiki->config["table_prefix"]."users ".
126
                                        "WHERE ".
127
                                        "name = '".mysql_escape_string($nom_wiki)."' OR ".
128
                                        "email = '".mysql_escape_string($courriel)."'");
129
 
130
                        // pas inscrit ? on l'ajout à la base de données
131
                        if(empty($utilisateur_wiki_existe)) {
132
                                // mot de passe généré à l'arrache, le mieux serait de trouver celui de tela encodé
133
                                // mais en gérant bien le sso on peut s'en passer car l'utilisateur ne devrait jamais avoir 
134
                                // à s'identifier par le wiki
135
                                $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
136
                                $pass = substr(str_shuffle(str_repeat($pool, 16)), 0, 16);
137
 
138
                                $this->wiki->Query("insert into ".$this->wiki->config["table_prefix"]."users set ".
139
                                                "signuptime = now(), ".
140
                                                "name = '".mysql_escape_string($token_decode['nomWiki'])."', ".
141
                                                "email = '".mysql_escape_string($token_decode['sub'])."', ".
142
                                                "password = md5('".mysql_escape_string($pass)."')");
143
                        } else {
144
                                // Un utilisateur peut déjà s'être inscrit sur le wiki avec un autre nom que son pseudo
145
                                $nom_wiki = $utilisateur_wiki_existe[0]['name'];
146
                                // s'il existe un enregistrement avec ce mail et un autre avec ce nomWiki on garde celui qui correspond au bon courriel
147
                                foreach($utilisateur_wiki_existe as $utilisateur_wiki) {
148
                                        if($utilisateur_wiki['email'] == $courriel) {
149
                                                  $nom_wiki = $utilisateur_wiki['name'];
150
                                        }
151
                                }
152
                        }
153
                }
154
 
155
                return $nom_wiki;
156
        }
157
 
158
        function recupererIdentiteConnectee() {
159
                $infos_cookie = $this->getInfosCookie();
160
                if($infos_cookie == null || $infos_cookie['tentative_identification'] == false) {      
161
                        // peut importe si l'annuaire répond oui ou non, on a fait une tentative d'identification
162
                        // et si on a trouvé quelqu'un on ne réésaiera pas jusqu'à la fermeture du navigateur
163
                        $infos_cookie = array('tentative_identification' => true, 'expire' => 0);
164
                        $this->setInfosCookie($infos_cookie);
165
 
166
                        $annuaire_url = $this->wiki->config['sso_url'].'identite';
167
                        // Attention si le paramètre wiki de l'url est vide, la redirection de retour pose des problèmes
168
                        $url = $annuaire_url.'?redirect_url='.urlencode($this->wiki->config['base_url'].$this->getPage());
169
 
170
                        header('Location: '.$url);
171
                        exit;
172
                } else {
173
                        $token = $this->getToken();
174
 
175
                        if($token != null) {
176
                                // On demande à l'annuaire si le jeton est bien valide
177
                                $jeton_rafraichi = json_decode(file_get_contents($this->wiki->config['sso_url'].'rafraichir?token='.$token), true);
178
                                $nom_wiki = $this->verifierEtInsererUtilisateurParJeton($jeton_rafraichi);
179
 
180
                                // dans le pire des cas, si on se déconnecte dans une autre application, on sera déconnecté 
181
                                // lorsque le jeton expirera
182
                                $infos_cookie = array('tentative_identification' => true, 'expire' => time()+$jeton_rafraichi['duration']);
183
                                $this->setInfosCookie($infos_cookie);
184
 
185
                                $this->wiki->SetUser($this->wiki->LoadUser($nom_wiki));
186
                        } else {
187
                                // personne n'a été trouvé ? on remplace le cookie par un de durée plus courte 
188
                                // pour rééssayer dans delai_tentative_identification si on en a pas déjà un
189
                                if($infos_cookie['expire'] == 0) {
190
                                        $infos_cookie['expire'] = time()+$this->delai_tentative_identification;
191
                                        $this->setInfosCookie($infos_cookie);
192
                                }
193
                        }
194
                }
195
        }
196
 
65 aurelien 197
        function recupererIdentiteConnecteePourApi() {         
198
                $token = $this->getToken();
199
                if($token != null) {
200
                        // On demande à l'annuaire si le jeton est bien valide
201
                        $jeton_rafraichi = json_decode(file_get_contents($this->wiki->config['sso_url'].'rafraichir?token='.$token), true);
202
                        $nom_wiki = $this->verifierEtInsererUtilisateurParJeton($jeton_rafraichi);
203
                        $this->wiki->SetUser($this->wiki->LoadUser($nom_wiki));
204
                }
205
        }
63 aurelien 206
 
207
        function connecterUtilisateur($login, $pass, $url_redirect = null) {
208
                if(strpos($login, '@') === false) {
209
                        $utilisateur_wiki = $this->wiki->LoadSingle("SELECT email FROM  ".$this->wiki->config["table_prefix"]."users ".
210
                        "WHERE name = '".mysql_escape_string($login)."'");
211
 
212
                        $login = !empty($utilisateur_wiki) ? $utilisateur_wiki['email'] : $login;
213
                        // TODO: si le courriel a changé dans l'annuaire, on devrait mettre à jour les informations 
214
                        // si on a utilisé le nom wiki pour s'identifier mais le flow du programme rend cela complexe
215
                }
216
 
217
                $url_redirect = ($url_redirect == null) ? $this->wiki->config['base_url'].'PagePrincipale' : $url_redirect;
218
 
219
                // le cookie de tentative d'identification est remis à zéro pour qu'au rechargement de la page il vérifie l'identité 
220
                // connectée du nouvel utilisateur
221
                $infos_cookie = array('tentative_identification' => false, 'expire' => 0);
222
                $this->setInfosCookie($infos_cookie);
223
                // On demande à l'annuaire si l'utilisateur est bien valide
224
                $annuaire_url = $this->wiki->config['sso_url'].'connexion?login='.$login.'&password='.$pass;
225
                $url = $annuaire_url.'&redirect_url='.urlencode($url_redirect);
226
 
227
                header('Location: '.$url);
228
                exit;
229
        }
230
 
231
        function deconnecterUtilisateur($url_redirect = null) {
232
                $url_redirect = ($url_redirect == null) ? $this->wiki->config['base_url'].'PagePrincipale' : $url_redirect;
233
                // Suppression d'un eventuel jeton contenu dans l'url
234
                $url_redirect = $this->supprimerUrlVar($url_redirect, 'Authorization');
235
 
236
                $infos_cookie = array('tentative_identification' => false, 'expire' => 0);
237
                $this->setInfosCookie($infos_cookie);
238
                // On demande à l'annuaire si l'utilisateur est bien valide
239
                $annuaire_url = $this->wiki->config['sso_url'].'deconnexion';
240
                $url = $annuaire_url.'?redirect_url='.urlencode($url_redirect);
241
                header('Location: '.$url);
242
                exit;
243
        }
244
}
245
?>