Subversion Repositories Applications.papyrus

Rev

Rev 2154 | Rev 2156 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php

// Remplacement de apache_request_headers pour les vieux serveurs
// http://stackoverflow.com/questions/2916232/call-to-undefined-function-apache-request-headers
if(!function_exists('apache_request_headers')) {
        function apache_request_headers() {
                // Based on: http://www.iana.org/assignments/message-headers/message-headers.xml#perm-headers
                $arrCasedHeaders = array(
                                // HTTP
                                'Dasl'             => 'DASL',
                                'Dav'              => 'DAV',
                                'Etag'             => 'ETag',
                                'Mime-Version'     => 'MIME-Version',
                                'Slug'             => 'SLUG',
                                'Te'               => 'TE',
                                'Www-Authenticate' => 'WWW-Authenticate',
                                // MIME
                                'Content-Md5'      => 'Content-MD5',
                                'Content-Id'       => 'Content-ID',
                                'Content-Features' => 'Content-features',
                );
                $arrHttpHeaders = array();

                foreach($_SERVER as $strKey => $mixValue) {
                        if('HTTP_' !== substr($strKey, 0, 5)) {
                                continue;
                        }

                        $strHeaderKey = strtolower(substr($strKey, 5));

                        if(0 < substr_count($strHeaderKey, '_')) {
                                $arrHeaderKey = explode('_', $strHeaderKey);
                                $arrHeaderKey = array_map('ucfirst', $arrHeaderKey);
                                $strHeaderKey = implode('-', $arrHeaderKey);
                        }
                        else {
                                $strHeaderKey = ucfirst($strHeaderKey);
                        }

                        if(array_key_exists($strHeaderKey, $arrCasedHeaders)) {
                                $strHeaderKey = $arrCasedHeaders[$strHeaderKey];
                        }

                        $arrHttpHeaders[$strHeaderKey] = $mixValue;
                }
                return $arrHttpHeaders;
        }
}

class identificationSso {
        
        // Attention bien v�rifier la pr�sence des variables suivantes :
        // IDEN_UTILISE_SSO, IDEN_URL_SSO, IDEN_HEADER_SSO, IDEN_COOKIE_SSO
        // dans le fichier iden_config.inc.php
        private $cookie_tentative_identification = "";
        /** Une tentative par minute pour s'identifier suffit largement */
        private $delai_tentative_identification = 60;
        
        private $auth_header = 'Authorization';
        
        private $annuaire_url = '';
        
        private $bdd_annuaire = '';
        private $table_annuaire = '';
        private $champ_login = '';
        private $champ_mdp = '';
        
        private $communs_papyrus = null;

        public function __construct() {
                $this->communs_papyrus = $GLOBALS['_GEN_commun'];
                
                $this->cookie_tentative_identification = IDEN_COOKIE_SSO;
                $this->auth_header = IDEN_HEADER_SSO;   
                $this->annuaire_url = IDEN_URL_SSO;
                
                // c'est moche mais je n'ai pas trouv� plus simple pour r�cuperer la table annuaire en cours 
                // d'utilisation pour le site actuel (la bdd annuaire est la derni�re partie du dsn)
                $dsn_annuaire = $this->communs_papyrus['info_auth_bdd']->gsab_dsn;
                $dsn_annuaire = explode('/', $dsn_annuaire);
                $this->bdd_annuaire = end($dsn_annuaire);
                
                $this->table_annuaire = $this->communs_papyrus['info_auth_bdd']->gsab_nom_table;
                $this->champ_login = $this->communs_papyrus['info_auth_bdd']->gsab_nom_champ_login;
                $this->champ_mdp = $this->communs_papyrus['info_auth_bdd']->gsab_nom_champ_mdp;
        }

        function getToken() {
                // Premier essai, dans le header
                $headers = @apache_request_headers();
                $token = !empty($headers['Authorization']) ? $headers['Authorization'] : null;
                // Eventuellement, le jeton a pu �tre pass� dans un header non standard, comme dans 
                // le cas o� le header Authorization est supprim� par le mod cgi d'apache
                // Dans ce cas l� on v�rifie aussi dans un header alternatif si celui ci a �t� renseign�
                if($token == null && $this->auth_header != 'Authorization') {
                        $token = !empty($headers[$this->auth_header]) ? $headers[$this->auth_header] : null;
                }

                // Sinon dans $_REQUEST ?
                if($token == null) {
                        $token = !empty($_REQUEST['Authorization']) ? $_REQUEST['Authorization'] : null;
                }
                
                // Sinon dans $_COOKIE ?
                if($token == null) {
                        $token = !empty($_COOKIE['tb_auth']) ? $_COOKIE['tb_auth'] : null;
                }

                return $token;
        }

        public function decoderToken($token) {
                $token_parts = explode('.', $token);
                return json_decode(base64_decode($token_parts[1]), true);
        }

        // http://stackoverflow.com/questions/1251582/beautiful-way-to-remove-get-variables-with-php?lq=1
        function supprimerUrlVar($url, $var) {
                 return rtrim(preg_replace('/([?&])'.$var.'=[^&]+(&|$)/','$1',$url), '&?');
        }
        
        function connecterEtRediriger() {
                $url_redirect = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
                $params = 'login='.$_POST['username'].'&password='.$_POST['password'].'&redirect_url='.urlencode($url_redirect);
                $connexion_url = $this->annuaire_url."connexion?".$params;
                
                header('Location: '.$connexion_url);
                exit;
        }
        
        function deconnecterEtRediriger() {
                $url_redirect = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
                $url_redirect = $this->supprimerUrlVar($url_redirect, 'logout');
                
                $deconnexion_url = $this->annuaire_url."deconnexion?".'redirect_url='.urlencode($url_redirect);
                
                header('Location: '.$deconnexion_url);
                exit;
        }
        
        function verifierIdentiteEtRediriger() {
                // si on fait autre chose qu'un GET, on ne vérifie pas l'identité, car
                // cela conduirait à une redirection en GET (avec le jeton), qui
                // supprimerait les données du corps de la requête
                if ($_SERVER['REQUEST_METHOD'] == "GET") {
                        if(empty($_COOKIE['sso_tentative_identification'])) {

                                if($this->communs_papyrus['pear_auth']->getAuth()) {

                                        $cookie_persistant_nom = session_name().'-memo';
                                        $cookie_utilisateur_nom = session_name().'-utilisateur';

                                        // Si l'utilisateur est d�j� connect� par pear
                                        // on fait tout de m�me une op�ration de logout
                                        // pour coordonner la d�connection depuis une autre application
                                        $this->communs_papyrus['pear_auth']->logout();
                                        // Destruction du cookie de session de Papyrus : est ce utile?
                                        setcookie(session_name(), session_id(), time()-3600, '/');
                                        // Destruction du cookie de permanence de l'identitification de Papyrus
                                        setcookie($cookie_persistant_nom, '', time()-3600, '/');
                                        setcookie($cookie_utilisateur_nom, '', time()-3600, '/');
                                }

                                $url_redirect = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
                                $url = $this->annuaire_url."identite?redirect_url=".urlencode($url_redirect);

                                // une tentative toutes les $this->delai_tentative_identification
                                setcookie($this->cookie_tentative_identification, 1, time() + $this->delai_tentative_identification, '/');

                                header('Location: '.$url);

                        } else {
                                $jeton = $this->getToken();

                                if($jeton != null) {
                                        // Verification du jeton aupres de l'annuaire
                                        $valide = $this->verifierToken($jeton);
                                        if ($valide === true) {
                                                $jeton_decode = $this->decoderToken($jeton);

                                                // R�cup�ration du mot de passe pour remplir les infos de l'objet PEAR Auth
                                                $requete =  'SELECT '.$this->champ_mdp.' '.
                                                                'FROM '.$this->bdd_annuaire.'.'.$this->table_annuaire.' '.
                                                                'WHERE '.$this->champ_login.' = "'.$jeton_decode['sub'].'" ';

                                                // TODO: normalement �a n'est jamais le cas mais que fait t'on si l'utilisateur n'existe pas
                                                // dans notre base de donn�es ? (au pire il ne sera pas connect�)

                                                $this->communs_papyrus['pear_auth']->username = $jeton_decode['sub'];
                                                $this->communs_papyrus['pear_auth']->password = $this->communs_papyrus['pear_db']->getOne($requete);

                                                // Le mot de passe est d�j� crypt� dans la bdd donc il faut indiquer � pear de ne pas le re crytper
                                                if (isset($this->communs_papyrus['pear_auth']->storage_options)) {
                                                        $this->communs_papyrus['pear_auth']->storage_options['cryptType'] = 'none';
                                                }
                                                if (isset($this->communs_papyrus['pear_auth']->storage->options)) {
                                                        $this->communs_papyrus['pear_auth']->storage->options['cryptType'] = 'none';
                                                }
                                        }
                                }
                        }
                }
        }

        /**
         * Vérifie un jeton auprès de l'annuaire
         */
        protected function verifierToken($token) {
                $verificationServiceURL = $this->annuaire_url . "verifytoken";
                $verificationServiceURL .= "?token=" . $token;

                $info = file_get_contents($verificationServiceURL);
                $info = json_decode($info, true);

                return ($info === true);
        }
}
?>