From e9fedf3e5cd63aea4da7a71f6647ee427c62fa49 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 5 Dec 2015 20:31:27 -0500 Subject: Rewrite of the authentication and authorization system --- app/Core/Security/AuthenticationManager.php | 187 ++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 app/Core/Security/AuthenticationManager.php (limited to 'app/Core/Security/AuthenticationManager.php') diff --git a/app/Core/Security/AuthenticationManager.php b/app/Core/Security/AuthenticationManager.php new file mode 100644 index 00000000..cced58c0 --- /dev/null +++ b/app/Core/Security/AuthenticationManager.php @@ -0,0 +1,187 @@ +providers[$provider->getName()] = $provider; + return $this; + } + + /** + * Register a new authentication provider + * + * @access public + * @param string $name + * @return AuthenticationProviderInterface|OAuthAuthenticationProviderInterface|PasswordAuthenticationProviderInterface|PreAuthenticationProviderInterface|OAuthAuthenticationProviderInterface + */ + public function getProvider($name) + { + if (! isset($this->providers[$name])) { + throw new LogicException('Authentication provider not found: '.$name); + } + + return $this->providers[$name]; + } + + /** + * Execute providers that are able to validate the current session + * + * @access public + * @return boolean + */ + public function checkCurrentSession() + { + if ($this->userSession->isLogged() ) { + foreach ($this->filterProviders('SessionCheckProviderInterface') as $provider) { + if (! $provider->isValidSession()) { + unset($this->sessionStorage->user); + $this->preAuthentication(); + return false; + } + } + } + + return true; + } + + /** + * Execute pre-authentication providers + * + * @access public + * @return boolean + */ + public function preAuthentication() + { + foreach ($this->filterProviders('PreAuthenticationProviderInterface') as $provider) { + if ($provider->authenticate() && $this->userProfile->initialize($provider->getUser())) { + $this->dispatcher->dispatch(self::EVENT_SUCCESS, new AuthSuccessEvent($provider->getName())); + return true; + } + } + + return false; + } + + /** + * Execute username/password authentication providers + * + * @access public + * @param string $username + * @param string $password + * @param boolean $fireEvent + * @return boolean + */ + public function passwordAuthentication($username, $password, $fireEvent = true) + { + foreach ($this->filterProviders('PasswordAuthenticationProviderInterface') as $provider) { + $provider->setUsername($username); + $provider->setPassword($password); + + if ($provider->authenticate() && $this->userProfile->initialize($provider->getUser())) { + if ($fireEvent) { + $this->dispatcher->dispatch(self::EVENT_SUCCESS, new AuthSuccessEvent($provider->getName())); + } + + return true; + } + } + + if ($fireEvent) { + $this->dispatcher->dispatch(self::EVENT_FAILURE, new AuthFailureEvent($username)); + } + + return false; + } + + /** + * Perform OAuth2 authentication + * + * @access public + * @param string $name + * @return boolean + */ + public function oauthAuthentication($name) + { + $provider = $this->getProvider($name); + + if ($provider->authenticate() && $this->userProfile->initialize($provider->getUser())) { + $this->dispatcher->dispatch(self::EVENT_SUCCESS, new AuthSuccessEvent($provider->getName())); + return true; + } + + $this->dispatcher->dispatch(self::EVENT_FAILURE, new AuthFailureEvent); + + return false; + } + + /** + * Get the last Post-Authentication provider + * + * @access public + * @return PostAuthenticationProviderInterface + */ + public function getPostAuthenticationProvider() + { + $providers = $this->filterProviders('PostAuthenticationProviderInterface'); + + if (empty($providers)) { + throw new LogicException('You must have at least one Post-Authentication Provider configured'); + } + + return array_pop($providers); + } + + /** + * Filter registered providers by interface type + * + * @access private + * @param string $interface + * @return array + */ + private function filterProviders($interface) + { + $interface = '\Kanboard\Core\Security\\'.$interface; + + return array_filter($this->providers, function(AuthenticationProviderInterface $provider) use ($interface) { + return is_a($provider, $interface); + }); + } +} -- cgit v1.2.3 From 73ce90ac568909f04d28f41492f99b66ba3fb037 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 5 Dec 2015 21:34:26 -0500 Subject: Remove unused use statements --- app/Api/User.php | 2 +- app/Controller/Base.php | 1 - app/Controller/Customfilter.php | 2 ++ app/Core/Security/AuthenticationManager.php | 1 - app/Core/Session/SessionManager.php | 1 - app/Helper/Url.php | 1 - app/Helper/User.php | 2 -- app/Model/ProjectDailyColumnStats.php | 2 -- app/Model/ProjectDailyStats.php | 2 -- app/User/DatabaseUserProvider.php | 1 - app/User/OAuthUserProvider.php | 1 - 11 files changed, 3 insertions(+), 13 deletions(-) (limited to 'app/Core/Security/AuthenticationManager.php') diff --git a/app/Api/User.php b/app/Api/User.php index 078c82f1..06e305f2 100644 --- a/app/Api/User.php +++ b/app/Api/User.php @@ -2,7 +2,7 @@ namespace Kanboard\Api; -use Kanboard\Auth\Ldap; +use LogicException; use Kanboard\Core\Security\Role; use Kanboard\Core\Ldap\Client as LdapClient; use Kanboard\Core\Ldap\ClientException as LdapException; diff --git a/app/Controller/Base.php b/app/Controller/Base.php index 76948a0f..35ceee09 100644 --- a/app/Controller/Base.php +++ b/app/Controller/Base.php @@ -2,7 +2,6 @@ namespace Kanboard\Controller; -use Pimple\Container; use Kanboard\Core\Security\Role; /** diff --git a/app/Controller/Customfilter.php b/app/Controller/Customfilter.php index ef75a837..12cc8e78 100644 --- a/app/Controller/Customfilter.php +++ b/app/Controller/Customfilter.php @@ -2,6 +2,8 @@ namespace Kanboard\Controller; +use Kanboard\Core\Security\Role; + /** * Custom Filter management * diff --git a/app/Core/Security/AuthenticationManager.php b/app/Core/Security/AuthenticationManager.php index cced58c0..dbc41b09 100644 --- a/app/Core/Security/AuthenticationManager.php +++ b/app/Core/Security/AuthenticationManager.php @@ -4,7 +4,6 @@ namespace Kanboard\Core\Security; use LogicException; use Kanboard\Core\Base; -use Kanboard\Core\User\UserProviderInterface; use Kanboard\Event\AuthFailureEvent; use Kanboard\Event\AuthSuccessEvent; diff --git a/app/Core/Session/SessionManager.php b/app/Core/Session/SessionManager.php index 750711b0..776d02da 100644 --- a/app/Core/Session/SessionManager.php +++ b/app/Core/Session/SessionManager.php @@ -3,7 +3,6 @@ namespace Kanboard\Core\Session; use Kanboard\Core\Base; -use Kanboard\Core\Http\Request; /** * Session Manager diff --git a/app/Helper/Url.php b/app/Helper/Url.php index 3658ef5f..6ada8068 100644 --- a/app/Helper/Url.php +++ b/app/Helper/Url.php @@ -2,7 +2,6 @@ namespace Kanboard\Helper; -use Kanboard\Core\Http\Request; use Kanboard\Core\Base; /** diff --git a/app/Helper/User.php b/app/Helper/User.php index b242dbb4..101d8dbe 100644 --- a/app/Helper/User.php +++ b/app/Helper/User.php @@ -2,8 +2,6 @@ namespace Kanboard\Helper; -use Kanboard\Core\Security\Role; - /** * User helpers * diff --git a/app/Model/ProjectDailyColumnStats.php b/app/Model/ProjectDailyColumnStats.php index 4b75fff2..7c89283d 100644 --- a/app/Model/ProjectDailyColumnStats.php +++ b/app/Model/ProjectDailyColumnStats.php @@ -2,8 +2,6 @@ namespace Kanboard\Model; -use PicoDb\Database; - /** * Project Daily Column Stats * diff --git a/app/Model/ProjectDailyStats.php b/app/Model/ProjectDailyStats.php index 7ec1ee2c..e79af372 100644 --- a/app/Model/ProjectDailyStats.php +++ b/app/Model/ProjectDailyStats.php @@ -2,8 +2,6 @@ namespace Kanboard\Model; -use PicoDb\Database; - /** * Project Daily Stats * diff --git a/app/User/DatabaseUserProvider.php b/app/User/DatabaseUserProvider.php index b6d41186..9a0047b2 100644 --- a/app/User/DatabaseUserProvider.php +++ b/app/User/DatabaseUserProvider.php @@ -3,7 +3,6 @@ namespace Kanboard\User; use Kanboard\Core\User\UserProviderInterface; -use Kanboard\Core\Security\Role; /** * Database User Provider diff --git a/app/User/OAuthUserProvider.php b/app/User/OAuthUserProvider.php index 3879fa76..527fefde 100644 --- a/app/User/OAuthUserProvider.php +++ b/app/User/OAuthUserProvider.php @@ -3,7 +3,6 @@ namespace Kanboard\User; use Kanboard\Core\User\UserProviderInterface; -use Kanboard\Core\Security\Role; /** * OAuth User Provider -- cgit v1.2.3 From d0e809a32cd58c0d89b2425aeb245e04a94df7d6 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 6 Dec 2015 08:23:53 -0500 Subject: Add new method to flush session variables --- app/Core/Security/AuthenticationManager.php | 2 +- app/Core/Session/SessionStorage.php | 15 +++++++++++++++ tests/units/Core/Session/SessionStorageTest.php | 22 ++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) (limited to 'app/Core/Security/AuthenticationManager.php') diff --git a/app/Core/Security/AuthenticationManager.php b/app/Core/Security/AuthenticationManager.php index dbc41b09..8e5f76be 100644 --- a/app/Core/Security/AuthenticationManager.php +++ b/app/Core/Security/AuthenticationManager.php @@ -71,7 +71,7 @@ class AuthenticationManager extends Base if ($this->userSession->isLogged() ) { foreach ($this->filterProviders('SessionCheckProviderInterface') as $provider) { if (! $provider->isValidSession()) { - unset($this->sessionStorage->user); + $this->sessionStorage->flush(); $this->preAuthentication(); return false; } diff --git a/app/Core/Session/SessionStorage.php b/app/Core/Session/SessionStorage.php index 11230793..f55a7ee3 100644 --- a/app/Core/Session/SessionStorage.php +++ b/app/Core/Session/SessionStorage.php @@ -61,6 +61,21 @@ class SessionStorage return $session; } + /** + * Flush session data + * + * @access public + */ + public function flush() + { + $session = get_object_vars($this); + unset($session['storage']); + + foreach (array_keys($session) as $property) { + unset($this->$property); + } + } + /** * Copy class properties to external storage * diff --git a/tests/units/Core/Session/SessionStorageTest.php b/tests/units/Core/Session/SessionStorageTest.php index 62495e5e..dd0040d5 100644 --- a/tests/units/Core/Session/SessionStorageTest.php +++ b/tests/units/Core/Session/SessionStorageTest.php @@ -35,4 +35,26 @@ class SessionStorageTest extends Base $storage = null; $this->assertEquals(array('something' => array('a' => 'c'), 'd' => 'e'), $session); } + + public function testFlush() + { + $session = array('d' => 'e'); + + $storage = new SessionStorage(); + $storage->setStorage($session); + $storage->something = array('a' => 'b'); + + $this->assertEquals(array('a' => 'b'), $storage->something); + $this->assertEquals('e', $storage->d); + + $storage->flush(); + + $this->assertFalse(isset($storage->d)); + $this->assertFalse(isset($storage->something)); + + $storage->foo = 'bar'; + + $storage = null; + $this->assertEquals(array('foo' => 'bar'), $session); + } } -- cgit v1.2.3 From 8f6c064cd7652635751c91283f6b35f652f52885 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 6 Dec 2015 14:55:45 -0500 Subject: Add debug log for session invalidation --- app/Core/Security/AuthenticationManager.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app/Core/Security/AuthenticationManager.php') diff --git a/app/Core/Security/AuthenticationManager.php b/app/Core/Security/AuthenticationManager.php index 8e5f76be..b1ba76cf 100644 --- a/app/Core/Security/AuthenticationManager.php +++ b/app/Core/Security/AuthenticationManager.php @@ -68,9 +68,10 @@ class AuthenticationManager extends Base */ public function checkCurrentSession() { - if ($this->userSession->isLogged() ) { + if ($this->userSession->isLogged()) { foreach ($this->filterProviders('SessionCheckProviderInterface') as $provider) { if (! $provider->isValidSession()) { + $this->logger->debug('Invalidate session for '.$this->userSession->getUsername()); $this->sessionStorage->flush(); $this->preAuthentication(); return false; -- cgit v1.2.3