diff --git a/lib/Cake/Controller/Component/Auth/BaseAuthenticate.php b/lib/Cake/Controller/Component/Auth/BaseAuthenticate.php index db476bb37eb..f0b4a96fd16 100644 --- a/lib/Cake/Controller/Component/Auth/BaseAuthenticate.php +++ b/lib/Cake/Controller/Component/Auth/BaseAuthenticate.php @@ -98,6 +98,18 @@ protected function _findUser($username, $password) { */ abstract public function authenticate(CakeRequest $request, CakeResponse $response); +/** + * Allows you to hook into AuthComponent::logout(), + * and implement specialized logout behaviour. + * + * All attached authentication objects will have this method + * called when a user logs out. + * + * @param array $user The user about to be logged out. + * @return void + */ + public function logout($user) { } + /** * Get a user based on information in the request. Primarily used by stateless authentication * systems like basic and digest auth. @@ -108,4 +120,4 @@ abstract public function authenticate(CakeRequest $request, CakeResponse $respon public function getUser($request) { return false; } -} \ No newline at end of file +} diff --git a/lib/Cake/Controller/Component/AuthComponent.php b/lib/Cake/Controller/Component/AuthComponent.php index 4063fc1446c..a8a7e0b7181 100644 --- a/lib/Cake/Controller/Component/AuthComponent.php +++ b/lib/Cake/Controller/Component/AuthComponent.php @@ -516,6 +516,9 @@ public function login($user = null) { /** * Logs a user out, and returns the login action to redirect to. + * Triggers the logout() method of all the authenticate objects, so they can perform + * custom logout logic. AuthComponent will remove the session data, so + * there is no need to do that in an authentication object. * * @param mixed $url Optional URL to redirect the user to after logout * @return string AuthComponent::$loginAction @@ -524,6 +527,13 @@ public function login($user = null) { */ public function logout() { $this->__setDefaults(); + if (empty($this->_authenticateObjects)) { + $this->constructAuthenticate(); + } + $user = $this->user(); + foreach ($this->_authenticateObjects as $auth) { + $auth->logout($user); + } $this->Session->delete(self::$sessionKey); $this->Session->delete('Auth.redirect'); return Router::normalize($this->logoutRedirect); diff --git a/lib/Cake/Test/Case/Controller/Component/AuthComponentTest.php b/lib/Cake/Test/Case/Controller/Component/AuthComponentTest.php index c2129a58103..fac3ece7844 100644 --- a/lib/Cake/Test/Case/Controller/Component/AuthComponentTest.php +++ b/lib/Cake/Test/Case/Controller/Component/AuthComponentTest.php @@ -1061,6 +1061,17 @@ public function testLogout() { $this->assertNull($this->Auth->Session->read('Auth.redirect')); } + public function testLogoutTrigger() { + $this->getMock('BaseAuthenticate', array('authenticate', 'logout'), array(), 'LogoutTriggerMockAuthenticate', false); + + $this->Auth->authenticate = array('LogoutTriggerMock'); + $mock = $this->Auth->constructAuthenticate(); + $mock[0]->expects($this->once()) + ->method('logout'); + + $this->Auth->logout(); + } + /** * test mapActions loading and delegating to authorize objects. *