Skip to content

Commit

Permalink
Added triggering of Auth.afterIdentify and Auth.logout events.
Browse files Browse the repository at this point in the history
Auth.afterIdentify is triggered after a user has been identified.
BaseAuthenticate::logout() has been removed, instead authenticate classes should
add listener for Auth.logout event if needed.
  • Loading branch information
ADmad committed Nov 6, 2014
1 parent 3f46309 commit 601cdcc
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 28 deletions.
36 changes: 22 additions & 14 deletions src/Auth/BaseAuthenticate.php
Expand Up @@ -16,6 +16,7 @@
use Cake\Auth\PasswordHasherFactory;
use Cake\Controller\ComponentRegistry;
use Cake\Core\InstanceConfigTrait;
use Cake\Event\EventListenerInterface;
use Cake\Network\Request;
use Cake\Network\Response;
use Cake\ORM\TableRegistry;
Expand All @@ -24,7 +25,7 @@
* Base Authentication class with common methods and properties.
*
*/
abstract class BaseAuthenticate {
abstract class BaseAuthenticate implements EventListenerInterface {

use InstanceConfigTrait;

Expand Down Expand Up @@ -174,19 +175,6 @@ public function needsPasswordRehash() {
*/
abstract public function authenticate(Request $request, Response $response);

/**
* Allows you to hook into AuthComponent::logout(),
* and implement specialized logout behavior.
*
* 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(array $user) {
}

/**
* Get a user based on information in the request. Primarily used by stateless authentication
* systems like basic and digest auth.
Expand All @@ -213,4 +201,24 @@ public function getUser(Request $request) {
public function unauthenticated(Request $request, Response $response) {
}

/**
* Returns a list of all events that this authenticate class will listen to.
*
* An autheticate class can listen to following events fired by AuthComponent:
*
* - `Auth.afterIdentify` - Fired after a user has been identified using one of
* configured authenticate class. The callback function should have signature
* like `afteIndentify(Event $event, array $user)` when `$user` is the
* identified user record.
*
* - `Auth.logout` - Fired when AuthComponent::logout() is called. The callback
* function should have signature like `logout(Event $event, array $user)`
* where `$user` is the user about to be logged out.
*
* @return array List of events this class listens to. Defaults to `[]`.
*/
public function implementedEvents() {
return [];
}

}
10 changes: 7 additions & 3 deletions src/Controller/Component/AuthComponent.php
Expand Up @@ -19,6 +19,7 @@
use Cake\Core\App;
use Cake\Core\Exception\Exception;
use Cake\Event\Event;
use Cake\Event\EventManagerTrait;
use Cake\Network\Exception\ForbiddenException;
use Cake\Network\Request;
use Cake\Network\Response;
Expand All @@ -34,6 +35,8 @@
*/
class AuthComponent extends Component {

use EventManagerTrait;

/**
* Constant for 'all'
*
Expand Down Expand Up @@ -236,6 +239,7 @@ class AuthComponent extends Component {
*/
public function initialize(array $config) {
$controller = $this->_registry->getController();
$this->eventManager($controller->eventManager());
$this->request = $controller->request;
$this->response = $controller->response;
$this->session = $controller->request->session();
Expand Down Expand Up @@ -599,9 +603,7 @@ public function logout() {
$this->constructAuthenticate();
}
$user = (array)$this->user();
foreach ($this->_authenticateObjects as $auth) {
$auth->logout($user);
}
$this->dispatchEvent('Auth.logout', [$user]);
$this->session->delete($this->sessionKey);
$this->session->delete('Auth.redirect');
$this->session->renew();
Expand Down Expand Up @@ -716,6 +718,7 @@ public function identify() {
$result = $auth->authenticate($this->request, $this->response);
if (!empty($result) && is_array($result)) {
$this->_authenticationProvider = $auth;
$event = $this->dispatchEvent('Auth.afterIdentify', [$result]);
return $result;
}
}
Expand Down Expand Up @@ -755,6 +758,7 @@ public function constructAuthenticate() {
}
$config = array_merge($global, (array)$config);
$this->_authenticateObjects[$alias] = new $className($this->_registry, $config);
$this->eventManager()->attach($this->_authenticateObjects[$alias]);
}
return $this->_authenticateObjects;
}
Expand Down
21 changes: 10 additions & 11 deletions tests/TestCase/Controller/Component/AuthComponentTest.php
Expand Up @@ -1014,22 +1014,21 @@ public function testLogout() {
}

/**
* Logout should trigger a logout method on authentication objects.
* Test that Auth.afterIdentify and Auth.logout events are triggered
*
* @return void
*/
public function testLogoutTrigger() {
$LogoutTriggerMockAuthenticate = $this->getMock(
'Cake\Controller\Component\Auth\BaseAuthenticate',
array('authenticate', 'logout'), array(), '', false
);

$this->Auth->config('authenticate', ['LogoutTriggerMock']);
$this->Auth->setAuthenticateObject(0, $LogoutTriggerMockAuthenticate);
$LogoutTriggerMockAuthenticate->expects($this->once())
->method('logout');
public function testEventTriggering() {
$this->Auth->config('authenticate', [
'Test' => ['className' => 'TestApp\Auth\TestAuthenticate']
]);

$this->Auth->identify();
$this->Auth->logout();
$authObject = $this->Auth->authenticationProvider();

$expected = ['afterIdentify', 'logout'];
$this->assertEquals($expected, $authObject->callStack);
}

/**
Expand Down
48 changes: 48 additions & 0 deletions tests/test_app/TestApp/Auth/TestAuthenticate.php
@@ -0,0 +1,48 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 3.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace TestApp\Auth;

use Cake\Auth\BaseAuthenticate;
use Cake\Event\Event;
use Cake\Network\Request;
use Cake\Network\Response;

/**
* TestAuthenticate class
*
*/
class TestAuthenticate extends BaseAuthenticate {

public $callStack = [];

public function implementedEvents() {
return [
'Auth.afterIdentify' => 'afterIdentify',
'Auth.logout' => 'logout'
];
}

public function authenticate(Request $request, Response $response) {
return ['id' => 1, 'username' => 'admad'];
}

public function afterIdentify(Event $event, array $user) {
$this->callStack[] = __FUNCTION__;
}

public function logout(Event $event, array $user) {
$this->callStack[] = __FUNCTION__;
}

}

0 comments on commit 601cdcc

Please sign in to comment.