Source for file jAuth.class.php

Documentation is available at jAuth.class.php

  1. <?php
  2. /**
  3. @package    jelix
  4. @subpackage auth
  5. @author     Laurent Jouanneau
  6. @contributor Frédéric Guillot, Antoine Detante, Julien Issler, Dominique Papin, Tahina Ramaroson, Sylvain de Vathaire, Vincent Viaud
  7. @copyright  2001-2005 CopixTeam, 2005-2016 Laurent Jouanneau, 2007 Frédéric Guillot, 2007 Antoine Detante
  8. @copyright  2007-2008 Julien Issler, 2008 Dominique Papin, 2010 NEOV, 2010 BP2I
  9. *
  10. *  This classes were get originally from an experimental branch of the Copix project (Copix 2.3dev, http://www.copix.org)
  11. *  Few lines of code are still copyrighted 2001-2005 CopixTeam (LGPL licence).
  12. *  Initial author of this Copix classes is Laurent Jouanneau, and this classes were adapted for Jelix by him
  13. @licence  http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public Licence, see LICENCE file
  14. */
  15.  
  16. require(JELIX_LIB_PATH.'auth/jIAuthDriver.iface.php');
  17.  
  18. require(JELIX_LIB_PATH.'auth/jAuthDriverBase.class.php');
  19.  
  20.  
  21.  
  22. /**
  23.  * This is the main class for authentification process
  24.  * @package    jelix
  25.  * @subpackage auth
  26.  */
  27. class jAuth {
  28.  
  29.     /**
  30.      * @deprecated
  31.      * @see jAuth::getConfig()
  32.      */
  33.     protected static function _getConfig({
  34.         return self::loadConfig();
  35.     }
  36.  
  37.     protected static $config null;
  38.     protected static $driver null;
  39.     /**
  40.      * Load the configuration of authentification, stored in the auth plugin config
  41.      * @return array 
  42.      * @since 1.2.10
  43.      */
  44.     public static function loadConfig($newconfig null){
  45.  
  46.         if (self::$config === null || $newconfig{
  47.             if (!$newconfig{
  48.                 $plugin jApp::coord()->getPlugin('auth');
  49.                 if($plugin === null)
  50.                     throw new jException('jelix~auth.error.plugin.missing');
  51.                 $config $plugin->config;
  52.             }
  53.             else {
  54.                 $config $newconfig;
  55.             }
  56.  
  57.             if (!isset($config['session_name'])
  58.                 || $config['session_name'== '')
  59.                 $config['session_name''JELIX_USER';
  60.  
  61.             if (!isset$config['persistant_cookie_path'])
  62.                 ||  $config['persistant_cookie_path'== ''{
  63.                 if (jApp::config())
  64.                     $config['persistant_cookie_path'jApp::config()->urlengine['basePath'];
  65.                 else
  66.                     $config['persistant_cookie_path''/';
  67.             }
  68.  
  69.             // Read hash method configuration. If not empty, cryptPassword will use
  70.             // the new API of PHP 5.5 (password_verify and so on...)
  71.             $password_hash_method (isset($config['password_hash_method'])$config['password_hash_method']:0);
  72.  
  73.             if ($password_hash_method === '' || (is_numeric($password_hash_method))) {
  74.                 $password_hash_method 0;
  75.             }
  76.             else {
  77.                 $password_hash_methodintval($password_hash_method);
  78.             }
  79.  
  80.             if ($password_hash_method 0{
  81.                 require_once(__DIR__.'/password.php');
  82.                 if (!can_use_password_API()) {
  83.                     $password_hash_method 0;
  84.                 }
  85.             }
  86.             else {
  87.                 require_once(__DIR__.'/hash_equals.php');
  88.             }
  89.  
  90.             $password_hash_options (isset($config['password_hash_options'])?$config['password_hash_options']:'');
  91.             if ($password_hash_options != ''{
  92.                 $list '{"'.str_replace(array('=',';')array('":"''","')$config['password_hash_options']).'"}';
  93.                 $json new jJson(SERVICES_JSON_LOOSE_TYPE);
  94.                 $password_hash_options @$json->decode($list);
  95.                 if (!$password_hash_options)
  96.                     $password_hash_options array();
  97.             }
  98.             else {
  99.                 $password_hash_options array();
  100.             }
  101.  
  102.             $config['password_hash_method'$password_hash_method;
  103.             $config['password_hash_options'$password_hash_options;
  104.  
  105.             $config[$config['driver']]['password_hash_method'$password_hash_method;
  106.             $config[$config['driver']]['password_hash_options'$password_hash_options;
  107.             self::$config $config;
  108.         }
  109.         return self::$config;
  110.     }
  111.  
  112.     /**
  113.      * @deprecated
  114.      * @see jAuth::getDriver()
  115.      */
  116.     protected static function _getDriver({
  117.         return self::getDriver();
  118.     }
  119.  
  120.     /**
  121.      * return the auth driver
  122.      * @return jIAuthDriver 
  123.      * @since 1.2.10
  124.      */
  125.     public static function getDriver(){
  126.         if (self::$driver === null{
  127.             $config self::loadConfig();
  128.             $db strtolower($config['driver']);
  129.             $driver jApp::loadPlugin($db'auth''.auth.php'$config['driver'].'AuthDriver'$config[$config['driver']]);
  130.             if(is_null($driver))
  131.                 throw new jException('jelix~auth.error.driver.notfound',$db);
  132.             self::$driver $driver;
  133.         }
  134.         return self::$driver;
  135.     }
  136.  
  137.     /**
  138.      * return the value of a parameter of the configuration of the current driver
  139.      * @param string $paramName 
  140.      * @return string the value. null if it doesn't exist
  141.      */
  142.     public static function getDriverParam($paramName{
  143.         $config self::loadConfig();
  144.         $config $config[$config['driver']];
  145.         if(isset($config[$paramName]))
  146.             return $config[$paramName];
  147.         else
  148.             return null;
  149.     }
  150.  
  151.     /**
  152.      * load user data
  153.      *
  154.      * This method returns an object, generated by the driver, and which contains
  155.      * data corresponding to the given login. This method should be called if you want
  156.      * to update data of a user. see updateUser method.
  157.      *
  158.      * @param string $login 
  159.      * @return object the user
  160.      */
  161.     public static function getUser($login){
  162.         $dr self::getDriver();
  163.         return $dr->getUser($login);
  164.     }
  165.  
  166.     /**
  167.      * Create a new user object
  168.      *
  169.      * You should call this method if you want to create a new user. It returns an object,
  170.      * representing a user. Then you should fill its properties and give it to the saveNewUser
  171.      * method.
  172.      *
  173.      * @param string $login the user login
  174.      * @param string $password the user password (not encrypted)
  175.      * @return object the returned object depends on the driver
  176.      * @since 1.0b2
  177.      */
  178.     public static function createUserObject($login,$password){
  179.         $dr self::getDriver();
  180.         return $dr->createUserObject($login,$password);
  181.     }
  182.  
  183.     /**
  184.      * Save a new user
  185.      *
  186.      * if the saving has succeed, a AuthNewUser event is sent
  187.      * The given object should have been created by calling createUserObject method :
  188.      *
  189.      * example :
  190.      *  <pre>
  191.      *   $user = jAuth::createUserObject('login','password');
  192.      *   $user->email ='bla@foo.com';
  193.      *   jAuth::saveNewUser($user);
  194.      *  </pre>
  195.      *  the type of $user depends of the driver, so it can have other properties.
  196.      *
  197.      * @param  object $user the user data
  198.      * @return object the user (eventually, with additional data)
  199.      */
  200.     public static function saveNewUser($user){
  201.         $dr self::getDriver();
  202.         if($dr->saveNewUser($user))
  203.             jEvent::notify ('AuthNewUser'array('user'=>$user));
  204.         return $user;
  205.     }
  206.  
  207.     /**
  208.      * update user data
  209.      *
  210.      * It send a AuthUpdateUser event if the saving has succeed. If you want
  211.      * to change the user password, you must use jAuth::changePassword method
  212.      * instead of jAuth::updateUser method.
  213.      *
  214.      * The given object should have been created by calling getUser method.
  215.      * Example :
  216.      *  <pre>
  217.      *   $user = jAuth::getUser('login');
  218.      *   $user->email ='bla@foo.com';
  219.      *   jAuth::updateUser($user);
  220.      *  </pre>
  221.      *  the type of $user depends of the driver, so it can have other properties.
  222.      *
  223.      * @param object $user  user data
  224.      */
  225.     public static function updateUser($user){
  226.         $dr self::getDriver();
  227.         if($dr->updateUser($user=== false)
  228.             return false;
  229.  
  230.         if(self::isConnected(&& self::getUserSession()->login === $user->login){
  231.             $config self::loadConfig();
  232.             $_SESSION[$config['session_name']] $user;
  233.         }
  234.         jEvent::notify ('AuthUpdateUser'array('user'=>$user));
  235.         return true;
  236.     }
  237.  
  238.     /**
  239.      * remove a user
  240.      * send first AuthCanRemoveUser event, then if ok, send AuthRemoveUser
  241.      * and then remove the user.
  242.      * @param string $login the user login
  243.      * @return boolean true if ok
  244.      */
  245.     public static function removeUser($login){
  246.         $dr self::getDriver();
  247.         $eventresp jEvent::notify ('AuthCanRemoveUser'array('login'=>$login));
  248.         foreach($eventresp->getResponse(as $rep){
  249.             if(!isset($rep['canremove']|| $rep['canremove'=== false)
  250.                 return false;
  251.         }
  252.         $user $dr->getUser($login);
  253.         if($dr->removeUser($login)===false)
  254.             return false;
  255.         jEvent::notify ('AuthRemoveUser'array('login'=>$login'user'=>$user));
  256.         if(self::isConnected(&& self::getUserSession()->login === $login)
  257.             self::logout();
  258.         return true;
  259.     }
  260.  
  261.     /**
  262.      * construct the user list
  263.      * @param string $pattern '' for all users
  264.      * @return array array of object
  265.      */
  266.     public static function getUserList($pattern '%'){
  267.         $dr self::getDriver();
  268.         return $dr->getUserlist($pattern);
  269.     }
  270.  
  271.     /**
  272.      * change a user password
  273.      *
  274.      * @param string $login the login of the user
  275.      * @param string $newpassword the new password (not encrypted)
  276.      * @return boolean true if the change succeed
  277.      */
  278.     public static function changePassword($login$newpassword){
  279.         $dr self::getDriver();
  280.         if($dr->changePassword($login$newpassword)===false)
  281.             return false;
  282.         if(self::isConnected(&& self::getUserSession()->login === $login){
  283.             $config self::loadConfig();
  284.             $_SESSION[$config['session_name']] self::getUser($login);
  285.         }
  286.         return true;
  287.     }
  288.  
  289.     /**
  290.      * verify that the password correspond to the login
  291.      * @param string $login the login of the user
  292.      * @param string $password the password to test (not encrypted)
  293.      * @return object|false if ok, returns the user as object
  294.      */
  295.     public static function verifyPassword($login$password){
  296.         $dr self::getDriver();
  297.         return $dr->verifyPassword($login$password);
  298.     }
  299.  
  300.     /**
  301.      * authentificate a user, and create a user in the php session
  302.      * @param string $login the login of the user
  303.      * @param string $password the password to test (not encrypted)
  304.      * @param boolean $persistant (optional) the session must be persistant
  305.      * @return boolean true if authentification is ok
  306.      */
  307.     public static function login($login$password$persistant=false){
  308.  
  309.         $dr self::getDriver();
  310.         $config self::loadConfig();
  311.  
  312.         $eventresp jEvent::notify ('AuthBeforeLogin'array('login'=>$login));
  313.         foreach($eventresp->getResponse(as $rep){
  314.             if(isset($rep['processlogin']&& $rep['processlogin'=== false)
  315.                 return false;
  316.         }
  317.  
  318.         if($user $dr->verifyPassword($login$password)){
  319.  
  320.             $eventresp jEvent::notify ('AuthCanLogin'array('login'=>$login'user'=>$user));
  321.             foreach($eventresp->getResponse(as $rep){
  322.                 if(!isset($rep['canlogin']|| $rep['canlogin'=== false)
  323.                     return false;
  324.             }
  325.  
  326.             $_SESSION[$config['session_name']] $user;
  327.  
  328.             if ($persistant{
  329.                 $persistence self::generateCookieToken($login$password);
  330.             }
  331.             else {
  332.                 $persistence 0;
  333.             }
  334.  
  335.             jEvent::notify ('AuthLogin'array('login'=>$login'persistence'=>$persistence));
  336.             return true;
  337.         }else{
  338.             jEvent::notify ('AuthErrorLogin'array('login'=>$login));
  339.             return false;
  340.         }
  341.     }
  342.  
  343.     /**
  344.      * Check if persistant session is enabled in config
  345.      * @return boolean true if persistant session in enabled
  346.      */
  347.     public static function isPersistant(){
  348.         $config self::loadConfig();
  349.         if(!isset($config['persistant_enable']))
  350.             return false;
  351.         else
  352.             return $config['persistant_enable'];
  353.     }
  354.  
  355.     /**
  356.      * logout a user and delete the user in the php session
  357.      */
  358.     public static function logout(){
  359.  
  360.         $config self::loadConfig();
  361.         jEvent::notify ('AuthLogout'array('login'=>$_SESSION[$config['session_name']]->login));
  362.         $_SESSION[$config['session_name']] new jAuthDummyUser();
  363.  
  364.         if (isset($config['session_destroy']&& $config['session_destroy']{
  365.             $params session_get_cookie_params();
  366.             setcookie(session_name()''time(42000$params["path"]$params["domain"]$params["secure"]$params["httponly"]);
  367.             session_destroy();
  368.         }
  369.  
  370.         if(isset($config['persistant_enable']&& $config['persistant_enable']){
  371.             if(!isset($config['persistant_cookie_name']))
  372.                 throw new jException('jelix~auth.error.persistant.incorrectconfig','persistant_cookie_name, persistant_crypt_key');
  373.             setcookie($config['persistant_cookie_name'].'[auth]'''time(3600$config['persistant_cookie_path']""falsetrue);
  374.         }
  375.     }
  376.  
  377.     /**
  378.      * Says if the user is connected
  379.      * @return boolean 
  380.      */
  381.     public static function isConnected(){
  382.         $config self::loadConfig();
  383.         return (isset($_SESSION[$config['session_name']]&& $_SESSION[$config['session_name']]->login != '');
  384.     }
  385.  
  386.    /**
  387.     * return the user stored in the php session
  388.     * @return object the user data
  389.     */
  390.     public static function getUserSession (){
  391.         $config self::loadConfig();
  392.         if (isset ($_SESSION[$config['session_name']]))
  393.             $_SESSION[$config['session_name']] new jAuthDummyUser();
  394.         return $_SESSION[$config['session_name']];
  395.     }
  396.  
  397.     /**
  398.      * generate a password with random letters, numbers and special characters
  399.      * @param int $length the length of the generated password
  400.      * @param boolean $withoutSpecialChars (optional, default false) the generated password may be use this characters : !@#$%^&*?_,~
  401.      * @return string the generated password
  402.      */
  403.     public static function getRandomPassword($length 10$withoutSpecialChars false){
  404.         if ($length 10)
  405.             $length 10;
  406.         $nbNumber floor($length/4);
  407.         if ($nbNumber 2)
  408.             $nbNumber 2;
  409.         if ($withoutSpecialChars)
  410.             $nbSpec 0;
  411.         else {
  412.             $nbSpec floor($length/5);
  413.             if ($nbSpec 1)
  414.                 $nbSpec 1;
  415.         }
  416.  
  417.         $nbLower floor(($length-$nbNumber-$nbSpec)/2);
  418.         $nbUpper $length-$nbNumber-$nbLower-$nbSpec;
  419.  
  420.         $pass '';
  421.  
  422.         $letter "1234567890";
  423.         for($i=0;$i<$nbNumber;$i++)
  424.             $pass .= $letter[rand(0,9)];
  425.  
  426.         $letter '!@#$%^&*?_,~';
  427.         for($i=0;$i<$nbSpec;$i++)
  428.             $pass .= $letter[rand(0,11)];
  429.  
  430.         $letter "abcdefghijklmnopqrstuvwxyz";
  431.         for($i=0;$i<$nbLower;$i++)
  432.             $pass .= $letter[rand(0,25)];
  433.  
  434.         $letter "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  435.         for($i=0;$i<$nbUpper;$i++)
  436.             $pass .= $letter[rand(0,25)];
  437.  
  438.         return str_shuffle($pass);
  439.     }
  440.  
  441.     /**
  442.      *
  443.      */
  444.     public static function checkCookieToken({
  445.         $config self::loadConfig();
  446.         if (isset($config['persistant_enable']&& $config['persistant_enable'&& !self::isConnected()) {
  447.             if (isset($config['persistant_cookie_name']&& isset($config['persistant_crypt_key'])) {
  448.                 $cookieName $config['persistant_cookie_name'];
  449.                 if (isset($_COOKIE[$cookieName]['auth']&& strlen($_COOKIE[$cookieName]['auth'])>0{
  450.                     $decrypted jCrypt::decrypt($_COOKIE[$cookieName]['auth'],$config['persistant_crypt_key']);
  451.                     $decrypted @unserialize($decrypted);
  452.                     if ($decrypted && is_array($decrypted)) {
  453.                         list($login$password$decrypted;
  454.                         self::login($login$passwordtrue);
  455.                     }
  456.                 }
  457.                 if (isset($_COOKIE[$cookieName]['login'])) {
  458.                     // destroy deprecated cookies
  459.                     setcookie($cookieName.'[login]'''time(3600$config['persistant_cookie_path']);
  460.                     setcookie($cookieName.'[passwd]'''time(3600$config['persistant_cookie_path']);
  461.                 }
  462.             }
  463.             else {
  464.                 throw new jException('jelix~auth.error.persistant.incorrectconfig','persistant_cookie_name, persistant_crypt_key');
  465.             }
  466.         }
  467.     }
  468.  
  469.     public static function generateCookieToken($login$password{
  470.         $persistence 0;
  471.         $config self::loadConfig();
  472.  
  473.         // Add a cookie for session persistance, if enabled
  474.         if (isset($config['persistant_enable']&& $config['persistant_enable']{
  475.             if (!isset($config['persistant_crypt_key']|| !isset($config['persistant_cookie_name'])) {
  476.                 throw new jException('jelix~auth.error.persistant.incorrectconfig','persistant_cookie_name, persistant_crypt_key');
  477.             }
  478.  
  479.             if (isset($config['persistant_duration']))
  480.                 $persistence $config['persistant_duration']*86400;
  481.             else
  482.                 $persistence 86400// 24h
  483.             $persistence += time();
  484.             //$login = $_SESSION[$config['session_name']]->login;
  485.             $encrypted jCrypt::encrypt(serialize(array($login$password)),$config['persistant_crypt_key']);
  486.             setcookie($config['persistant_cookie_name'].'[auth]'$encrypted$persistence$config['persistant_cookie_path']""falsetrue);
  487.         }
  488.         return $persistence;
  489.     }
  490. }

Documentation generated on Wed, 04 Jan 2017 22:52:14 +0100 by phpDocumentor 1.4.3