diff --git a/VERSIONS_HOTLINE/143813 b/VERSIONS_HOTLINE/143813 new file mode 100644 index 0000000000000000000000000000000000000000..cb61586b242d5688017ef3b7de971f0b1dd5eb87 --- /dev/null +++ b/VERSIONS_HOTLINE/143813 @@ -0,0 +1 @@ + - ticket #143813 : Boite de Connexion : le bouton de déconnexion vous déconnecte des fournisseurs d'identité tiers. \ No newline at end of file diff --git a/library/Class/Auth/Cas.php b/library/Class/Auth/Cas.php index d7f7f0dbfdfd2fcb093ead00f89022bc5ea06797..c74b6f18b7a4eb15bcef187628b6c68b37bf4c5c 100644 --- a/library/Class/Auth/Cas.php +++ b/library/Class/Auth/Cas.php @@ -72,9 +72,13 @@ trait Trait_Auth_CasAware { $digital_resource = Class_DigitalResource::getInstance(); return ($plugin = $digital_resource->getPluginsSSOActions() - ->detect(function ($plugin) use ($service) { - return FALSE !== stristr($service, $plugin); - })) + ->detect(function ($plugin) use ($service) + { + if ( ! $plugin ) + return false; + + return FALSE !== stristr($service, $plugin); + })) ? $digital_resource->hasPermissionOn($plugin, $user) : true; } diff --git a/library/Class/Auth/Strategy.php b/library/Class/Auth/Strategy.php index 958231fda79e91c05fd4582c63a1ed728e807d77..7b7612c3cde8baa5054b037974fa809b65c4a035 100644 --- a/library/Class/Auth/Strategy.php +++ b/library/Class/Auth/Strategy.php @@ -21,10 +21,13 @@ abstract class Class_Auth_Strategy { + use Trait_Translator; + protected $redirect_url = '', + $_logout_redirect_url = '', $disable_redirect = false, $on_login_success_callback, $on_login_fail_callback, @@ -80,9 +83,37 @@ abstract class Class_Auth_Strategy { public function logout() { + if ( ! $user = Class_Users::getIdentity()) + return $this->controller->redirect($this->_getProfilRedirectUrl()); + + foreach (Class_User_Identity::findAllBy(['user_id' => $user->getId()]) as $identity) + $this->_logoutProvider($identity->getProvider()); + ZendAfi_Auth::getInstance()->clearIdentity(); (new Class_IdentityProvider_Types)->clearRemoteLogin(); - $this->controller->redirect($this->_getProfilRedirectUrl()); + $this->controller->redirect($this->_logout_redirect_url + ? $this->_logout_redirect_url + : $this->_getProfilRedirectUrl()); + } + + + protected function _logoutProvider($provider) { + if ( ! $provider) + return; + + if ( ! $provider->isRemotelyLogged()) + return; + + $provider->getConnector()->clearRemoteLogin(); + $this->_logout_redirect_url = $provider + ->getConnector() + ->logoutUrl($this->_getProfilRedirectUrl()); + } + + + public function setRedirectUrl($url) { + $this->redirect_url = $url; + return $this; } @@ -180,12 +211,6 @@ abstract class Class_Auth_Strategy { } - public function setRedirectUrl($url) { - $this->redirect_url = $url; - return $this; - } - - public function onLoginSuccess($do) { $this->on_login_success_callback = $do; return $this; diff --git a/library/Class/WebService/IdentityProvider.php b/library/Class/WebService/IdentityProvider.php index 0e2aa9c4d16e48cdb7ccc10eb3a64977759de5eb..892cff212eff13312c895616a003bf52a74bf509 100644 --- a/library/Class/WebService/IdentityProvider.php +++ b/library/Class/WebService/IdentityProvider.php @@ -44,6 +44,11 @@ abstract class Class_WebService_IdentityProvider { } + public static function setSession($called_class, $namespace) { + return static::$_session_namespace[$called_class] = $namespace; + } + + public static function setExpirationDelay($expires_at) { static::$_session_namespace[get_called_class()]->setExpirationDelay($expires_at); static::$_expiration_delay = $expires_at; diff --git a/tests/scenarios/IdentityProvider/IdentityProviderAuthenticationTest.php b/tests/scenarios/IdentityProvider/IdentityProviderAuthenticationTest.php index 2c2678e3cca689a33856709686ccc64c47c902d0..6c97aaa569ca2c0310cffdca52fb25cfdc2049d4 100644 --- a/tests/scenarios/IdentityProvider/IdentityProviderAuthenticationTest.php +++ b/tests/scenarios/IdentityProvider/IdentityProviderAuthenticationTest.php @@ -1379,3 +1379,69 @@ class IdentityProviderAuthenticationExpiringSessionAchetezaTest parent::tearDown(); } } + + + + +class IdentityProviderAuthenticationLogoutWithoutParamsTest extends AbstractControllerTestCase { + protected + $_storm_default_to_volatile = true, + $_session_namespace; + + + public function setUp() { + parent::setUp(); + + Class_AdminVar::set('ENABLE_IDENTITY_PROVIDERS', 1); + + $this->fixture('Class_IdentityProvider', + ['id' => 6, + 'label' => 'CAS 2.0', + 'type' => 'cas2', + 'config' => json_encode(['url' => 'https://moncas.securelogin.com']) + ]); + + $user = $this->fixture(Class_Users::class, + ['id' => 314, + 'login' => 'han.solo', + 'password' => 'F@lc0n']); + + $this->fixture('Class_User_Identity', + ['id' => 1, + 'provider_id' => 6, + 'user_id' => 314, + 'identifier' => '9763']); + + ZendAfi_Auth::getInstance()->logUser($user); + + $time_source = new TimeSourceForTest('2021-11-03 10:10:38'); + ZendAfi_Session_Namespace::setTimeSource($time_source); + + $this->_session_namespace = md5(BASE_URL . 'Class_WebService_Cas2'); + $namespace = (new ZendAfi_Session_Namespace($this->_session_namespace)) + ->__set('id', '112321'); + + Class_WebService_IdentityProvider::setSession('Class_WebService_Cas2', + $namespace); + } + + + /** @test */ + public function sessionShouldContainsExpectedSessionNamespace() { + $this->assertContains($this->_session_namespace, array_keys($_SESSION)); + } + + + /** @test */ + public function afterLogoutSessionShouldNotContainsExpectedSessionNamespace() { + $this->dispatch('/auth/logout'); + $this->assertFalse(isset($_SESSION[$this->_session_namespace])); + } + + + /** @test */ + public function afterLogoutShouldRedirectToSecureloginDotComLogoutUrl() { + $this->dispatch('/auth/logout'); + $this->assertRedirectContains('https://moncas.securelogin.com/logout?service=http'); + } +} \ No newline at end of file