Subversion Repositories Applications.papyrus

Compare Revisions

Ignore whitespace Rev 2155 → Rev 2156

/trunk/papyrus/applettes/identification/configuration/iden_config.inc.php
46,10 → 46,10
// +------------------------------------------------------------------------------------------------------+
// | CORPS du PROGRAMME |
// +------------------------------------------------------------------------------------------------------+
/** Constante stockant la valeur de la langue par défaut pour l'applette IDEN.*/
/** Constante stockant la valeur de la langue par d�faut pour l'applette IDEN.*/
define('IDEN_I18N_DEFAUT', GEN_I18N_ID_DEFAUT);
 
/** Constante stockant la valeur de durée de la session.*/
/** Constante stockant la valeur de dur�e de la session.*/
define('IDEN_AUTH_SESSION_DUREE', PAP_AUTH_SESSION_DUREE);
 
// Chemin vers les dossiers de l'applette
68,11 → 68,17
 
define('IDEN_UTILISE_SSO','1');
 
define('IDEN_URL_SSO','https://www.tela-botanica.org/service:annuaire:auth/');
//define('IDEN_URL_SSO','https://www.tela-botanica.org/service:annuaire:auth/');
define('IDEN_URL_SSO','https://localhost/service:annuaire:auth/');
 
define('IDEN_HEADER_SSO','Auth');
define('IDEN_COOKIE_SSO','sso_mandataire_papyrus');
 
define('IDEN_COOKIE_SSO','sso_tentative_identification');
/**
* si true, essaiera une synchronisation totale avec le SSO, mais qui fait plein
* de redirections; sinon, ne synchronisera que dans un sens : Papyrus => SSO
* mais SSO ≠> Papyrus
*/
define('IDEN_SSO_SYNC', true);
 
/* +--Fin du code ----------------------------------------------------------------------------------------+
*
81,8 → 87,8
* modification de la balise identification pour permettre de preciser un template. Ajout d une constante
*
* Revision 1.2 2006/11/20 17:30:40 jp_milcent
* Amélioration de la gestion de l'identification.
* Utilisation des durées de session correcte.
* Am�lioration de la gestion de l'identification.
* Utilisation des dur�es de session correcte.
* Suppression du code pour Spip non fonctionnel.
*
* Revision 1.1 2005/03/15 14:18:49 jpm
/trunk/papyrus/bibliotheque/classes/pap_identificationsso.class.php
47,32 → 47,56
}
}
 
// Attention bien v�rifier la pr�sence des variables suivantes :
// IDEN_UTILISE_SSO, IDEN_URL_SSO, IDEN_COOKIE_SSO, IDEN_SSO_SYNC
// dans le fichier iden_config.inc.php
class identificationSso {
/**
* si la valeur est vraiment vide, le cookie n'est pas posé, alors on met
* une valeur vide pas vide :)
*/
public static $VALEUR_JETON_VIDE = "jeton-vide";
 
protected $cookie_mandataire = "";
/** le cookie qui dure jusqu'à Vladivostok, si synchro partielle seulement */
protected $duree_cookie_mandataire = (3600 * 24 * 365);
 
/**
* lorsqu'appelé par un client non-navigateur (qui n'envoie et ne reçoit pas
* de cookies), permet de ne pas rediriger en boucle, en fournissant le
* paramètre GET "non_interactif"
*/
protected $mode_non_interactif = false;
 
/** voir IDEN_SSO_SYNC dans iden_config.inc.php */
protected $synchro_complete;
 
protected $annuaire_url = '';
protected $bdd_annuaire = '';
protected $table_annuaire = '';
protected $champ_login = '';
protected $champ_mdp = '';
// 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;
protected $communs_papyrus = null;
 
public function __construct() {
$this->communs_papyrus = $GLOBALS['_GEN_commun'];
$this->cookie_tentative_identification = IDEN_COOKIE_SSO;
$this->cookie_mandataire = IDEN_COOKIE_SSO;
$this->auth_header = IDEN_HEADER_SSO;
$this->annuaire_url = IDEN_URL_SSO;
$this->synchro_complete = IDEN_SSO_SYNC;
 
// gestion des clients qui ne gèrent pas les cookies (file_get_contents...)
if (isset($_GET['non_interactif'])) {
$this->mode_non_interactif = true;
}
 
// si on est en mode synchro complète, on vérifie périodiquement l'état
// du SSO, en utilisant un cookie qui ne dure pas jusqu'à Vladivostok
if ($this->synchro_complete === true) {
$this->duree_cookie_mandataire = 60; // une fois par minute (ça ou autre chose)
}
// 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)
85,134 → 109,236
$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;
// http://stackoverflow.com/questions/1251582/beautiful-way-to-remove-get-variables-with-php?lq=1
protected function supprimerUrlVar($url, $var) {
return rtrim(preg_replace('/([?&])'.$var.'=[^&]*(&|$)/','$1',$url), '&?');
}
 
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() {
/**
* Se connecte au SSO : redirige vers le service d'authentification, qui pose
* le cookie tb_auth, puis re-redirige vers Papyrus avec le jeton en GET, puis
* Papyrus stocke ce jeton dans son cookie mandataire, puis se re-redirige
* vers lui-même pour éliminer le paramètre GET de l'URL (ouf !)
*/
public function connecterEtRediriger() {
//echo "JE CONNECTE<br/>";
// sauvegarde de l'URL courante
$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;
// redirection vers l'annuaire, qui va nous connecter au SSO et nous
// renvoyer un jeton en GET
header('Location: '.$connexion_url);
exit;
}
function deconnecterEtRediriger() {
 
/**
* Se déconnecte du SSO : redirige vers le service d'authentification, qui
* supprime le cookie tb_auth, puis re-redirige vers Papyrus avec un jeton
* vide en GET; Papyrus stocke ce jeton vide dans son cookie mandataire,
* puis se re-redirige vers lui-même pour éliminer le paramètre GET de l'URL
*/
public function deconnecterEtRediriger() {
//echo "JE DECONNECTE<br/>";
// sauvegarde de l'URL courante
$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);
// redirection vers l'annuaire, qui va nous déconnecter du SSO et nous
// renvoyer un jeton vide en GET
header('Location: '.$deconnexion_url);
exit;
}
function verifierIdentiteEtRediriger() {
protected function synchroniserDepuisEtatSso() {
//echo "JE SYNCHRONISE<br/>";
// sauvegarde de l'URL courante
$url_redirect = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$params = 'redirect_url='.urlencode($url_redirect);
$identite_url = $this->annuaire_url."identite?".$params;
// redirection vers l'annuaire, qui va nous donner l'état du SSO et nous
// renvoyer un jeton en GET
header('Location: '.$identite_url);
exit;
}
 
/**
* Appelée à chaque chargement de page
*/
public 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()) {
// lecture jeton en GET si on vient de l'annuaire
if (isset($_GET['Authorization'])) {
//echo "Re-Redirection pour éliminer le GET<br/>";
 
$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, '/');
// création / mise à jour du cookie mandataire (le jeton peut être
// vide en cas de déconnexion)
$jetonRecu = $_GET['Authorization'];
if ($jetonRecu == '') {
$jetonRecu = self::$VALEUR_JETON_VIDE;
}
$this->setCookieMandataire($jetonRecu);
//echo "JETON REÇU: " . $_GET['Authorization'];
//echo "JETON POSÉ: "; var_dump($jetonRecu);
//exit;
 
// redirection pour éliminer le paramètre GET
$url_redirect = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$url = $this->annuaire_url."identite?redirect_url=".urlencode($url_redirect);
$url_redirect = $this->supprimerUrlVar($url_redirect, 'Authorization');
//echo "URL Redirect: $url_redirect"; exit;
header('Location: ' . $url_redirect);
exit;
}
 
// une tentative toutes les $this->delai_tentative_identification
setcookie($this->cookie_tentative_identification, 1, time() + $this->delai_tentative_identification, '/');
// une fois qu'on a fait une connexion ou une déconnexion, on se base
// sur le cookie mandataire pour gérer l'identité dans Papyrus
//var_dump($_COOKIE); echo "<br/>";
// lecture cookie mandataire de Papyrus
$jeton = null;
$cookiePresent = false;
if (isset($_COOKIE[$this->cookie_mandataire])) {
$cookiePresent = true;
$jeton = $_COOKIE[$this->cookie_mandataire];
}
//echo "Cookie Présent: "; var_dump($cookiePresent);
//echo "JETON: "; var_dump($jeton); echo "<br/>";
//exit;
 
header('Location: '.$url);
// s'il y a un cookie, qu'il contienne un jeton valide ou vide
if ($cookiePresent) {
// s'il contient un jeton non-vide
if ($jeton != self::$VALEUR_JETON_VIDE) {
// reconnexion PEAR (l'utilisateur peut avoir changé)
//echo "RECONNEXION!<br/>"; exit;
$this->deconnexionPear();
$this->connexionPear($jeton);
 
} else {
$jeton = $this->getToken();
// prolonge le cookie de 30 secondes si on est connecté, pour
// minimiser les synchros avec le SSO
$this->setCookieMandataire($jeton, 30);
 
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';
// si mode synchro partielle, le cookie mandataire dure logntemps,
// on rafraîchit donc le jeton pour... euh... on sait jamais :-/
if (! $this->synchro_complete) {
// appel annuaire / identité avec jeton en GET
$infosJson = $this->rafraichirJeton($jeton);
$infos = json_decode($infosJson, true);
//echo "INFOS: "; var_dump($infos); echo "<br/>";
$jetonRafraichi = null;
if (isset($infos['token'])) {
$jetonRafraichi = $infos['token'];
}
if (isset($this->communs_papyrus['pear_auth']->storage->options)) {
$this->communs_papyrus['pear_auth']->storage->options['cryptType'] = 'none';
//echo "JETON Rafraîchi: "; var_dump($jetonRafraichi); echo "<br/>";
//exit;
// si jeton rafraîchi reçu
if ($jetonRafraichi != null) {
// màj cookie avec jeton rafraîchi
$this->setCookieMandataire($jetonRafraichi);
// reconnexion PEAR (l'utilisateur peut avoir changé)
$this->deconnexionPear();
$this->connexionPear($jetonRafraichi);
//exit;
} else {
// sinon (non connecté ou problème annuaire / jeton)
// écriture cookie avec jeton vide
$this->setCookieMandataire(self::$VALEUR_JETON_VIDE);
// déconnexion PEAR
$this->deconnexionPear();
}
}
} else {
// déconnexion PEAR ?
$this->deconnexionPear();
}
} else { // sinon (aucun cookie mandataire)
// en mode synchro complète, on vérifie chaque minute (lorsque le
// cookie mandataire n'est plus présent) si on n'est pas connecté
// sur le SSO, sauf si on est en mode non interactif
if ($this->synchro_complete && (! $this->mode_non_interactif)) {
$this->synchroniserDepuisEtatSso();
}
}
}
}
 
protected function setCookieMandataire($valeur, $duree=null) {
if ($duree === null) {
$duree = $this->duree_cookie_mandataire;
}
setcookie($this->cookie_mandataire, $valeur, time() + $duree);
}
 
/**
* Vérifie un jeton auprès de l'annuaire
* Connecte l'utilisateur à Papyrus avec le système traditionnel fourni par PEAR
*/
protected function verifierToken($token) {
$verificationServiceURL = $this->annuaire_url . "verifytoken";
$verificationServiceURL .= "?token=" . $token;
protected function connexionPear($jeton) {
$jeton_decode = $this->decoderToken($jeton);
 
$info = file_get_contents($verificationServiceURL);
$info = json_decode($info, true);
// 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'].'" ';
 
return ($info === true);
// 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';
}
 
// si on fait pas ça, ça marche pas (régénération de session apparemment)
//$this->communs_papyrus['pear_auth']->setAuth($jeton_decode['sub']);
}
 
/**
* Supprime tout ce qui a trait à PEAR afin de déconnecter l'utilisateur du
* système d'authentification traditionnel de Papyrus
*/
protected function deconnexionPear() {
$this->communs_papyrus['pear_auth']->logout();
 
$cookie_persistant_nom = session_name().'-memo';
$cookie_utilisateur_nom = session_name().'-utilisateur';
// 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, '/');
}
 
/**
* Fournit un jeton à l'annuaire (jeton provenant du cookie mandataire
* de Papyrus), le fait rafraîchir puis met à jour le cookie mandataire avec
* le jeton rafraîchi
*/
protected function rafraichirJeton($jeton) {
$identiteServiceURL = $this->annuaire_url . "identite";
$identiteServiceURL .= "?token=" . $jeton;
//echo "URL: $identiteServiceURL<br/>";
$ch = curl_init($identiteServiceURL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$jetonRafraichi = curl_exec($ch);
//var_dump($jetonRafraichi);
//var_dump(curl_error($ch)); exit;
 
return $jetonRafraichi;
}
 
protected function decoderToken($token) {
$token_parts = explode('.', $token);
return json_decode(base64_decode($token_parts[1]), true);
}
}
?>