helper = $data; $this->escaper = $escaper; $this->timezone = $timezone; $this->storeManager = $storeManager; $this->configHelper = $configHelper; $this->failedAuthFactory = $failedAuthFactory; $this->failedAuthResource = $failedAuthResource; parent::__construct($context); } /** * Auth. */ public function authenticate() { //in locked state if ($this->isAuthLocked()) { $this->sendUnauthorizedResponse(); return false; } //passcode not valid. if (!$this->helper->auth($this->getRequest()->getParam('code'))) { $this->processFailedRequest(); $this->sendUnauthorizedResponse(); return false; } //ip is not allowed if (!$this->helper->isIpAllowed()) { $this->sendNoContentResponse(); return false; } return true; } /** * */ public function execute() { } /** * @return \Zend\Http\PhpEnvironment\Response */ public function sendUnauthorizedResponse() { $this->getResponse() ->setHttpResponseCode(401) ->setHeader('Pragma', 'public', true) ->setHeader( 'Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true ) ->setHeader('Content-type', 'text/html; charset=UTF-8', true) ->setBody('

401 Unauthorized

'); return $this->getResponse()->sendHeaders(); } /** * @return \Zend\Http\PhpEnvironment\Response */ public function sendNoContentResponse() { try { $this->getResponse() ->setHttpResponseCode(204) ->setHeader('Pragma', 'public', true) ->setHeader( 'Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true ) ->setHeader('Content-type', 'text/html; charset=UTF-8', true); return $this->getResponse()->sendHeaders(); } catch (\Exception $e) { $this->helper->log($e); } } /** * Register the failed attempt and set a lock with a 5min window if more then 5 request failed. */ private function processFailedRequest() { $url = $this->_url->getCurrentUrl(); $storeId = $this->storeManager->getStore()->getId(); $failedAuth = $this->failedAuthFactory->create(); $this->failedAuthResource->load($failedAuth, $storeId, 'store_id'); $numOfFails = $failedAuth->getFailuresNum(); $lastAttemptDate = $failedAuth->getLastAttemptDate(); //set the first failed attempt if (!$failedAuth->getId()) { $failedAuth->setFirstAttemptDate(time()); } //check the time for the last fail and update the records if ($numOfFails == \Dotdigitalgroup\Email\Model\FailedAuth::NUMBER_MAX_FAILS_LIMIT) { //ignore the resource is in a locked state if ($failedAuth->isLocked()) { $this->helper->log(sprintf('Resource locked time : %s ,store : %s', $lastAttemptDate, $storeId)); return; } else { //reset with the first lock after the the lock expired $numOfFails = 0; $failedAuth->setFirstAttemptDate(time()); } } try { $failedAuth->setFailuresNum(++$numOfFails) ->setStoreId($storeId) ->setUrl($url) ->setLastAttemptDate(time()); $this->failedAuthResource->save($failedAuth); } catch (\Exception $e) { $this->helper->log($e); } } /** * @return bool */ private function isAuthLocked() { $failedAuth = $this->failedAuthFactory->create(); $storeId = $this->storeManager->getStore()->getId(); $this->failedAuthResource->load($failedAuth, $storeId, 'store_id'); return $failedAuth->isLocked(); } }