3  * Piwik - Open source web analytics
 
   5  * @link http://piwik.org
 
   6  * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
 
   9  * @category Piwik_Plugins
 
  13 namespace Piwik\Plugins\CASLogin;
 
  20 use Piwik\Plugins\UsersManager\API;
 
  23  * Class that implements an authentication mechanism via CAS (Central Authentication Services)
 
  25  * @package Piwik_CASLogin
 
  27 class Auth implements \Piwik\Auth
 
  29         protected $login = null;
 
  30         protected $token_auth = null;
 
  31         private static $phpcas_client_called = false;
 
  33         public function getName()
 
  38         public function initSession($login, $md5Password, $rememberMe) {}
 
  40         public function authenticate()
 
  44                 require_once PIWIK_INCLUDE_PATH . '/plugins/CASLogin/CAS/CAS.php';
 
  48                 // What happens here: in some piwik functionality, some additional API-style calls are
 
  49                 // made from a controller action, where the authenticate() method will be called *again*.
 
  50                 // This happens for instance when an admin changes some permissions in Settings->Users.
 
  51                 // The first authenticate() is from the page, and the second is due to an API call.
 
  52                 // This checks if there was already a phpcas instance already initialized, otherwize
 
  53                 // phpCAS::client() would fail.
 
  54                 if (!self::$phpcas_client_called) {
 
  56                                 constant( Config::getInstance()->caslogin['protocol'] ),
 
  57                                 Config::getInstance()->caslogin['host'],
 
  58                                 (integer) Config::getInstance()->caslogin['port'],
 
  62                         self::$phpcas_client_called = true;
 
  65                 // no SSL validation for the CAS server
 
  66                 \phpCAS::setNoCasServerValidation();
 
  68                 // Handle single signout requests from CAS server
 
  69                 \phpCAS::handleLogoutRequests();
 
  71                 // force CAS authentication only if it has been requested by action argument
 
  72                 $action = Piwik::getAction();
 
  74                 $auth = \phpCAS::checkAuthentication();
 
  76                         if($action == 'redirectToCAS') {
 
  77                                 phpCAS::forceAuthentication();
 
  80                         if($action != 'login' && Piwik::getModule() != 'CoreUpdater') {
 
  81                                 Piwik::redirectToModule('CASLogin', 'login');
 
  83                         } elseif($action == 'redirectToCAS') {
 
  84                                 phpCAS::forceAuthentication();
 
  86                                 return new AuthResult( AuthResult::FAILURE, $user, NULL );
 
  90                 // Additional Attributes
 
  91                 // For future retrieval of attributes; they _might_ be of some use, but are highly
 
  92                 // dependable on a specific installation. CAS|piwik hackers can do some magic
 
  93                 // here with SAML attributes etc.
 
  95                 foreach (\phpCAS::getAttributes() as $key => $value) {
 
  96                         // syslog(LOG_DEBUG, "attribute: $key - ". print_r($value, true));
 
 100                 if (isset($_SESSION['phpCAS']) && isset($_SESSION['phpCAS']['user'])) {
 
 101                         $user = $_SESSION['phpCAS']['user'];
 
 105                         $db_user = Db::fetchRow('SELECT login, superuser_access FROM '.Common::prefixTable('user').' WHERE login = ?',
 
 108                         if($db_user === null) {
 
 109                                 // ***User Autocreate***
 
 110                                 // We can either add the authenticated but not-yet-authorized user to the piwik users
 
 111                                 // database, or ignore that.
 
 112                                 // TODO: make this a config option
 
 113                                 $this->_populateDb($user);
 
 118                                 $login = $db_user['login'];
 
 119                                 $superuser = $db_user['superuser_access'];
 
 124                                         $code = AuthResult::SUCCESS_SUPERUSER_AUTH_CODE;
 
 125                                 else $code = AuthResult::SUCCESS; 
 
 126                                 return new AuthResult($code, $login, NULL );
 
 130                 return new AuthResult( AuthResult::FAILURE, $user, NULL );
 
 133         public function setLogin($login)
 
 135                 $this->login = $login;
 
 137     public function getLogin() {
 
 141     public function setTokenAuth($token_auth)
 
 143                 $this->token_auth = $token_auth;
 
 145     public function getTokenAuthSecret() {
 
 146         return $this->token_auth;
 
 150          * This method is used to inject user into Piwik's tables.
 
 151          * @todo Alias could be the 'cn' returned from CAS attributes.
 
 153         private function _populateDb($user)
 
 156                 $dummy = md5('abcd1234');
 
 157                 if ($this->_helper_userExists($user)) {
 
 158                         $this->_helper_updateUser($user, $dummy, '', $user);
 
 160                         $this->_helper_addUser($user, $dummy, '', $user);
 
 165         ///// The following methods are taken from Piwik's UserManager, but in order to inject data into piwik's user and access tables, we need
 
 166         ///// to make sure we don't wreck things. The UserManager API uses authenticate() to check if we're eligable to look this up,
 
 167         ///// soi we can't use it - we need superuser permissions anyway.
 
 169         ///// Warning - these methods are of course under Piwik's license.
 
 170         private function _helper_userExists($name)
 
 172                 $count = Db::fetchOne("SELECT count(*)
 
 173                                                                         FROM ".Common::prefixTable("user"). "
 
 174                                                                         WHERE login = ?", $name);
 
 178         private function _helper_updateUser( $userLogin, $password = false, $email = false, $alias = false ) 
 
 180                 $token_auth = API::getTokenAuth($userLogin, $password);
 
 182                 Db::get()->update( Common::prefixTable("user"),
 
 184                                                 'password' => $password,
 
 187                                                 'token_auth' => $token_auth,
 
 189                                         "login = '$userLogin'"
 
 193         private function _helper_addUser( $userLogin, $password, $email, $alias = false )
 
 195                 $token_auth = API::getTokenAuth($userLogin, $password);
 
 197                 Db::get()->insert( Common::prefixTable("user"), array(
 
 198                                                                         'login' => $userLogin,
 
 199                                                                         'password' => $password,
 
 202                                                                         'token_auth' => $token_auth,
 
 207     // Those methods are required by Piwik API.
 
 208     public function setPassword($password) {}
 
 209     public function setPasswordHash($passwordHash) {}