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 * @package Piwik_CASLogin
13 * Class that implements an authentication mechanism via CAS (Central Authentication Services)
15 * @package Piwik_CASLogin
17 class Piwik_CASLogin_Auth implements Piwik_Auth
19 protected $login = null;
20 protected $token_auth = null;
22 public function getName()
27 public function authenticate()
30 $rootLogin = Zend_Registry::get('config')->superuser->login;
32 $additionalSuperUsers = array();
33 $oAdditionalSuperUsers = Zend_Registry::get('config')->caslogin->additionalsuperusers;
34 if(is_object($oAdditionalSuperUsers)) {
35 $additionalSuperUsers = $oAdditionalSuperUsers->toArray();
38 require_once PIWIK_INCLUDE_PATH . '/plugins/CASLogin/CAS/CAS.php';
42 // What happens here: in some piwik functionality, some additional API-style calls are
43 // made from a controller action, where the authenticate() method will be called *again*.
44 // This happens for instance when an admin changes some permissions in Settings->Users.
45 // The first authenticate() is from the page, and the second is due to an API call.
46 // This checks if there was already a phpcas instance already initialized, otherwize
47 // phpCAS::client() would fail.
48 global $PHPCAS_CLIENT;
49 if(!is_object($PHPCAS_CLIENT)) {
51 constant( Zend_Registry::get('config')->caslogin->protocol ),
52 Zend_Registry::get('config')->caslogin->host,
53 (integer) Zend_Registry::get('config')->caslogin->port,
59 // no SSL validation for the CAS server
60 phpCAS::setNoCasServerValidation();
62 // Handle single signout requests from CAS server
63 phpCAS::handleLogoutRequests();
65 // force CAS authentication only if it has been requested by action argument
66 $action = Piwik::getAction();
68 $auth = phpCAS::checkAuthentication();
70 if($action == 'redirectToCAS') {
71 phpCAS::forceAuthentication();
74 if($action != 'login' && Piwik::getModule() != 'CoreUpdater') {
75 Piwik::redirectToModule('CASLogin', 'login');
77 } elseif($action == 'redirectToCAS') {
78 phpCAS::forceAuthentication();
80 return new Piwik_Auth_Result( Piwik_Auth_Result::FAILURE, $user, NULL );
84 // Additional Attributes
85 // For future retrieval of attributes; they _might_ be of some use, but are highly
86 // dependable on a specific installation. CAS|piwik hackers can do some magic
87 // here with SAML attributes etc.
89 foreach (phpCAS::getAttributes() as $key => $value) {
90 // syslog(LOG_DEBUG, "attribute: $key - ". print_r($value, true));
94 if (isset($_SESSION['phpCAS']) && isset($_SESSION['phpCAS']['user'])) {
95 $user = $_SESSION['phpCAS']['user'];
99 if($user == $rootLogin || in_array($user, $additionalSuperUsers)) {
100 // Root / Admin login
101 return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS_SUPERUSER_AUTH_CODE, $user, NULL );
104 $login = Zend_Registry::get('db')->fetchOne(
105 'SELECT login FROM '.Piwik_Common::prefixTable('user').' WHERE login = ?',
108 if($login === false) {
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);
119 return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS, $login, NULL );
123 return new Piwik_Auth_Result( Piwik_Auth_Result::FAILURE, $user, NULL );
126 public function setLogin($login)
128 $this->login = $login;
131 public function setTokenAuth($token_auth)
133 $this->token_auth = $token_auth;
137 * This method is used to inject user into Piwik's tables.
138 * @todo Alias could be the 'cn' returned from CAS attributes.
140 private function _populateDb($user)
143 $dummy = md5('abcd1234');
144 if ($this->_helper_userExists($user)) {
145 $this->_helper_updateUser($user, $dummy, '', 'alias');
147 $this->_helper_addUser($user, $dummy, '', 'alias');
152 ///// The following methods are taken from Piwik's UserManager, but in order to inject data into piwik's user and access tables, we need
153 ///// to make sure we don't wreck things. The UserManager API uses authenticate() to check if we're eligable to look this up,
154 ///// soi we can't use it - we need superuser permissions anyway.
156 ///// Warning - these methods are of course under Piwik's license.
157 private function _helper_userExists($name)
159 $count = Zend_Registry::get('db')->fetchOne("SELECT count(*)
160 FROM ".Piwik_Common::prefixTable("user"). "
161 WHERE login = ?", $name);
165 private function _helper_updateUser( $userLogin, $password = false, $email = false, $alias = false )
167 $token_auth = Piwik_UsersManager_API::getTokenAuth($userLogin, $password);
169 $db = Zend_Registry::get('db');
171 $db->update( Piwik_Common::prefixTable("user"),
173 'password' => $password,
176 'token_auth' => $token_auth,
178 "login = '$userLogin'"
182 private function _helper_addUser( $userLogin, $password, $email, $alias = false )
184 $token_auth = Piwik_UsersManager_API::getTokenAuth($userLogin, $password);
186 $db = Zend_Registry::get('db');
188 $db->insert( Piwik_Common::prefixTable("user"), array(
189 'login' => $userLogin,
190 'password' => $password,
193 'token_auth' => $token_auth,