From e23205e8e3440bf5dab13515fa3f7d644e15fef6 Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Thu, 23 Jul 2009 10:49:24 -0600 Subject: [PATCH] Horde_Auth improvements Standardize pre/post-authenticate hooks and ensure they are called for all authentication events. Use transparent() authentication to authenticate to applications that don't require any additional authentication. --- framework/Auth/lib/Horde/Auth.php | 65 +++++++++++++++++++-------- framework/Auth/lib/Horde/Auth/Application.php | 36 +++++++-------- framework/Auth/lib/Horde/Auth/Base.php | 33 ++++++++++---- 3 files changed, 89 insertions(+), 45 deletions(-) diff --git a/framework/Auth/lib/Horde/Auth.php b/framework/Auth/lib/Horde/Auth.php index f9c9b4a9e..f5e9eafc2 100644 --- a/framework/Auth/lib/Horde/Auth.php +++ b/framework/Auth/lib/Horde/Auth.php @@ -378,17 +378,10 @@ class Horde_Auth return self::checkExistingAuth(); } - if (empty($options['app'])) { - $auth = self::singleton($driver); - } else { - $auth = self::singleton('application', array('app' => $driver)); - - /* If we have a horde session, and the app doesn't need additional - * auth, mark that in the session and return. */ - if ($is_auth && !$auth->hasCapability('authenticate')) { - return self::setAuth($is_auth, self::getCredential(), array('app' => $driver)); - } - } + /* Try transparent authentication. */ + $auth = empty($options['app']) + ? self::singleton($driver) + : self::singleton('application', array('app' => $driver)); return $auth->transparent(); } @@ -639,13 +632,10 @@ class Horde_Auth $app = empty($options['app']) ? 'horde' : $options['app']; $userId = self::addHook(trim($userId)); - if (!empty($GLOBALS['conf']['hooks']['postauthenticate'])) { - if (Horde::callHook('_horde_hook_postauthenticate', array($userId, $credentials, $app), 'horde') === false) { - if (self::getAuthError() != self::REASON_MESSAGE) { - self::setAuthError(self::REASON_FAILED); - } - return false; - } + try { + list($userId, $credentials) = self::runHook($userId, $credentials, $app, 'postauthenticate'); + } catch (Horde_Auth_Exception $e) { + return false; } $app_array = array(); @@ -818,6 +808,45 @@ class Horde_Auth } /** + * Runs the pre/post-authenticate hook and parses the result. + * + * @param string $userId The userId who has been authorized. + * @param array $credentials The credentials of the user. + * @param string $app The app currently being authenticated. + * @param string $type Either 'preauthenticate' or + * 'postauthenticate'. + * + * @return array Two element array, $userId and $credentials. + * @throws Horde_Auth_Exception + */ + static public function runHook($userId, $credentials, $app, $type) + { + $ret_array = array($userId, $credentials); + + if (!empty($GLOBALS['conf']['hooks'][$type])) { + $result = Horde::callHook('_horde_hook_' . $type, array($userId, $credentials, $app), 'horde'); + if ($result === false) { + if (self::getAuthError() != self::REASON_MESSAGE) { + self::setAuthError(self::REASON_FAILED); + } + throw new Horde_Auth_Exception($type . ' hook failed'); + } + + if (is_array($result)) { + if (isset($result['userId'])) { + $ret_array[0] = $result['userId']; + } + + if (isset($result['credentials'])) { + $ret_array[1] = $result['credentials']; + } + } + } + + return $ret_array; + } + + /** * Returns the name of the authentication provider. * * @return string The name of the driver currently providing diff --git a/framework/Auth/lib/Horde/Auth/Application.php b/framework/Auth/lib/Horde/Auth/Application.php index 6df6e1981..d3549ee32 100644 --- a/framework/Auth/lib/Horde/Auth/Application.php +++ b/framework/Auth/lib/Horde/Auth/Application.php @@ -47,11 +47,13 @@ class Horde_Auth_Application extends Horde_Auth_Base * Constructor. * * @param array $params A hash containing connection parameters. + * @throws Horde_Exception */ public function __construct($params = array()) { Horde::assertDriverConfig($params, 'auth', array('app'), 'authentication application'); + $this->_app = $params['app']; parent::__construct($params); } @@ -70,7 +72,7 @@ class Horde_Auth_Application extends Horde_Auth_Base if (!in_array($capability, $this->_loaded) && isset($this->_apiMethods[$capability])) { $registry = Horde_Registry::singleton(); - $this->_capabilities[$capability] = $registry->hasMethod($this->_apiMethods[$capability], $this->_params['app']); + $this->_capabilities[$capability] = $registry->hasMethod($this->_apiMethods[$capability], $this->_app); $this->_loaded[] = $capability; } @@ -112,7 +114,7 @@ class Horde_Auth_Application extends Horde_Auth_Base protected function _authenticate($userId, $credentials) { if (!$this->hasCapability('authenticate')) { - throw new Horde_Auth_Exception($this->_params['app'] . ' does not provide an authenticate() method.'); + throw new Horde_Auth_Exception($this->_app . ' does not provide an authenticate() method.'); } $registry = Horde_Registry::singleton(); @@ -120,8 +122,7 @@ class Horde_Auth_Application extends Horde_Auth_Base $credentials['auth_ob'] = $this; try { - $result = $registry->callByPackage($this->_params['app'], $this->_apiMethods['authenticate'], array($userId, $credentials)); - $this->_credentials['params']['app'] = $this->_params['app']; + $result = $registry->callByPackage($this->_app, $this->_apiMethods['authenticate'], array($userId, $credentials)); } catch (Horde_Auth_Exception $e) { throw new Horde_Auth_Exception('', Horde_Auth::REASON_BADLOGIN); } @@ -137,7 +138,7 @@ class Horde_Auth_Application extends Horde_Auth_Base { if ($this->hasCapability('list')) { $registry = Horde_Registry::singleton(); - return $registry->callByPackage($this->_params['app'], $this->_apiMethods['list']); + return $registry->callByPackage($this->_app, $this->_apiMethods['list']); } else { return parent::listUsers(); } @@ -154,7 +155,7 @@ class Horde_Auth_Application extends Horde_Auth_Base { if ($this->hasCapability('exists')) { $registry = Horde_Registry::singleton(); - return $registry->callByPackage($this->_params['app'], $this->_apiMethods['exists'], array($userId)); + return $registry->callByPackage($this->_app, $this->_apiMethods['exists'], array($userId)); } else { return parent::exists($userId); } @@ -172,7 +173,7 @@ class Horde_Auth_Application extends Horde_Auth_Base { if ($this->hasCapability('add')) { $registry = Horde_Registry::singleton(); - $registry->callByPackage($this->_params['app'], $this->_apiMethods['exists'], array($userId, $credentials)); + $registry->callByPackage($this->_app, $this->_apiMethods['exists'], array($userId, $credentials)); } else { parent::addUser($userId, $credentials); } @@ -191,7 +192,7 @@ class Horde_Auth_Application extends Horde_Auth_Base { if ($this->hasCapability('update')) { $registry = Horde_Registry::singleton(); - $registry->callByPackage($this->_params['app'], $this->_apiMethods['update'], array($oldID, $newID, $credentials)); + $registry->callByPackage($this->_app, $this->_apiMethods['update'], array($oldID, $newID, $credentials)); } else { parent::updateUser($userId, $credentials); } @@ -208,7 +209,7 @@ class Horde_Auth_Application extends Horde_Auth_Base { if ($this->hasCapability('remove')) { $registry = Horde_Registry::singleton(); - $registry->callByPackage($this->_params['app'], $this->_apiMethods['remove'], array($userId)); + $registry->callByPackage($this->_app, $this->_apiMethods['remove'], array($userId)); Horde_Auth::removeUserData($userId); } else { parent::removeUser($userId); @@ -241,16 +242,15 @@ class Horde_Auth_Application extends Horde_Auth_Base protected function _transparent() { if (!$this->hasCapability('transparent')) { - return false; + /* If this application contains neither transparent nor + * authenticate capabilities, it does not require any + * authentication if already authenticated to Horde. */ + return (Horde_Auth::getAuth() && + !$this->hasCapability('authenticate')); } $registry = Horde_Registry::singleton(); - if (!$registry->callByPackage($this->_params['app'], $this->_apiMethods['transparent'])) { - return false; - } - - $this->_credentials['params']['app'] = $this->_params['app']; - return true; + return $registry->callByPackage($this->_app, $this->_apiMethods['transparent']); } /** @@ -269,7 +269,7 @@ class Horde_Auth_Application extends Horde_Auth_Base } $registry = Horde_Registry::singleton(); - return $registry->callByPackage($this->_params['app'], $this->_apiMethods['loginparams']); + return $registry->callByPackage($this->_app, $this->_apiMethods['loginparams']); } /** @@ -307,7 +307,7 @@ class Horde_Auth_Application extends Horde_Auth_Base { if ($this->hasCapability('authenticatecallback')) { $registry = Horde_Registry::singleton(); - $registry->callByPackage($this->_params['app'], $this->_apiMethods['authenticatecallback']); + $registry->callByPackage($this->_app, $this->_apiMethods['authenticatecallback']); } } diff --git a/framework/Auth/lib/Horde/Auth/Base.php b/framework/Auth/lib/Horde/Auth/Base.php index 974da44c5..9e8a547b5 100644 --- a/framework/Auth/lib/Horde/Auth/Base.php +++ b/framework/Auth/lib/Horde/Auth/Base.php @@ -50,6 +50,13 @@ abstract class Horde_Auth_Base ); /** + * Current application for authentication. + * + * @param string + */ + protected $_app = 'horde'; + + /** * Constructor. * * @param array $params A hash containing parameters. @@ -76,19 +83,17 @@ abstract class Horde_Auth_Base $auth = false; $userId = trim($userId); - if (!empty($GLOBALS['conf']['hooks']['preauthenticate'])) { - if (!Horde::callHook('_horde_hook_preauthenticate', array($userId, $credentials), 'horde')) { - if (Horde_Auth::getAuthError() != Horde_Auth::REASON_MESSAGE) { - Horde_Auth::setAuthError(Horde_Auth::REASON_FAILED); - } - return $auth; - } + try { + list($userId, $credentials) = Horde_Auth::runHook($userId, $credentials, $this->_app, 'preauthenticate'); + } catch (Horde_Auth_Exception $e) { + return false; } /* Store the credentials being checked so that subclasses can modify * them if necessary. */ $this->_credentials['credentials'] = $credentials; $this->_credentials['userId'] = $userId; + $this->_credentials['params']['app'] = $this->_app; try { $this->_authenticate($userId, $credentials); @@ -202,10 +207,20 @@ abstract class Horde_Auth_Base */ public function transparent() { + $userId = empty($this->_credentials['userId']) + ? Horde_Auth::getAuth() + : $this->_credentials['userId']; + $credentials = empty($this->_credentials['credentials']) + ? Horde_Auth::getCredential() + : $this->_credentials['credentials']; + + list($this->_credentials['userId'], $this->_credentials['credentials']) = Horde_Auth::runHook($userId, $credentials, $this->_app, 'preauthenticate'); + $this->_credentials['params']['app'] = $this->_app; + if ($this->_transparent()) { return Horde_Auth::setAuth( - empty($this->_credentials['userId']) ? Horde_Auth::getAuth() : $this->_credentials['userId'], - empty($this->_credentials['credentials']) ? Horde_Auth::getCredential() : $this->_credentials['credentials'], + $this->_credentials['userId'], + $this->_credentials['credentials'], $this->_credentials['params'] ); } -- 2.11.0