use Zend\Authentication\AuthenticationService; use Zend\EventManager\EventManager; class AuditLog { private $log; /** * AuditLog constructor. * @TODO add dependency for a psr logger * @param $log */ public function __construct($log) { $this->log = $log; } public function onAuthenticationFailed(\Zend\Authentication\Event\Authenticate $event) { $this->log->warn(sprintf('Authenication Failure for (%s) from (%s)', $event->getParam('identity'), $event->getParam('ip'))); } } $auditLog = new AuditLog(new stdClass()); $callback = function ($identity, $credential) { if ($identity === $credential) { return new \Zend\Stdlib\ArrayObject(['identity' => $identity, 'credential' => $credential]); } throw new \Exception('Authentication failed'); }; $adapter = new \Zend\Authentication\Adapter\Callback($callback); $authService = new AuthenticationService(null, $adapter); $authService->addListener('AuthenticationFailed', [$auditLog, 'onAuthenticationFailed'], -1); $authService->authenticate(['ip' => '127.0.0.1', 'identity' => 'test', 'credential' => 'failed']);
} } } public function onAuthenticationFailed(\Zend\Authentication\Event\Authenticate $event) { $identity = $event->getParam('identity'); if ($identity !== null) { $this->authFails[$identity]++; } $ip = $event->getParam('ip'); if ($ip !== null) { $this->authFails[$ip]++; } } } $firewall = new Firewall(); $callback = function ($identity, $credential) { if ($identity === $credential) { return new \Zend\Stdlib\ArrayObject(['identity' => $identity, 'credential' => $credential]); } throw new \Exception('Authentication failed'); }; $adapter = new \Zend\Authentication\Adapter\Callback($callback); $authService = new AuthenticationService(null, $adapter, 10); $authService->addListener('Authenticate', [$firewall, 'onAuthenticate'], -1); $authService->addListener('AuthenticationFailed', [$firewall, 'onAuthenticationFailed'], -1); $authService->authenticate(['ip' => '127.0.0.1', 'identity' => 'test', 'credential' => 'failed']); $authService->authenticate(['ip' => '127.0.0.1', 'identity' => 'test', 'credential' => 'failed']); $authService->authenticate(['ip' => '127.0.0.1', 'identity' => 'test2', 'credential' => 'failed']); // result = failure to many attempts $authService->authenticate(['ip' => '127.0.0.1', 'identity' => 'test2', 'credential' => 'failed']);
if (isset($twoFactorResponse)) { if ($prevResult !== null && isset($prevResult->twoFactorToken) && $twoFactorResponse === $prevResult->twoFactorToken) { $result = new \Zend\Authentication\Result(\Zend\Authentication\Result::SUCCESS, $identity); $event->setResult($result); return $result; } } $result = new \Zend\Authentication\Result(-4, $identity, 'Requires 2 factor Auth'); $result->twoFactorToken = 'efg456'; //generate randomly $event->setResult($result); $event->stopPropagation(); return $result; } } return $result; } } $twoFaListener = new TwoFAListener(); $callback = function ($identity, $credential) { if ($identity === $credential) { return new \Zend\Stdlib\ArrayObject(['identity' => $identity, 'credential' => $credential, 'do2fa' => true]); } throw new \Exception('Authentication failed'); }; $adapter = new \Zend\Authentication\Adapter\Callback($callback); $authService = new AuthenticationService(null, $adapter); $authService->addListener('Authenticate', [$TwoFAlistener, 'onAuthenticate'], 20); $authService->authenticate(['identity' => 'test', 'credential' => 'test']); //result success with test identity $authService->authenticate(['twoFactorResponse' => 'efg456']);