public function authenticate(AdapterChainEvent $e)
    {
        if ($this->isSatisfied()) {
            $storage = $this->getStorage()->read();
            $e->setIdentity($storage['identity'])
              ->setCode(Result::SUCCESS)
              ->setMessages(['Authentication successful']);

            return;
        }

        $post = $e->getRequest()->getPost();

        $identity = $post->get($e->getIdentityKey());
        $identityObject = $this->getMapper()->findByIdentity($identity);
        if (!$identityObject) {
            $e->setCode(Result::FAILURE_IDENTITY_NOT_FOUND)
              ->setMessages(['A record with the supplied identity could not be found']);
            $this->setSatisfied(false);

            return false;
        }

        if ($identityObject instanceof PasswordableInterface) {
            $credential = $post->get($e->getCredentialKey());
            $credential = $this->preprocessCredential($credential);
            $password   = $identityObject->getPassword();

            if (!$this->getMapper()->getPasswordService()->verify($credential, $password)) {
                // Password does not match
                $e->setCode(Result::FAILURE_CREDENTIAL_INVALID)
                  ->setMessages(['Supplied credential is invalid']);
                $this->setSatisfied(false);

                return false;
            }

            // Update user's password hash if the cost parameter has changed
            $this->updateCredentialHash($identityObject, $credential);
        }

        if ($identityObject instanceof StateableInterface) {
            $allowedStates = $this->options->getAllowedAuthenticationStates();

            // Don't allow user to login if state is not in allowed list
            if ($allowedStates && !in_array($identityObject->getState(), $allowedStates, true)) {
                $e->setCode(Result::FAILURE_UNCATEGORIZED)
                  ->setMessages(['A record with the supplied identity is disabled']);
                $this->setSatisfied(false);

                return false;
            }
        }

        if ($identityObject instanceof ExpirableInterface
            && null !== ($expireAt = $identityObject->getExpireAt())
            && $expireAt < new \DateTime('now')
        ) {
            $e->setCode(Result::FAILURE_UNCATEGORIZED)
              ->setMessages(['Record has expired']);
            $this->setSatisfied(false);

            return false;
        }

        // Regenerate the id
        $session = new Container($this->getStorage()->getNameSpace());
        $session->getManager()->regenerateId();

        // Success!
        $e->setIdentity($identityObject->getId());

        // Remember user if needed
        if ($post->get('rememberme') && ($ttl = $e->getRememberMeTimeout()) > 0) {
            $session->getManager()->rememberMe($ttl);
        }

        if ($identityObject instanceof LoginTrackableInterface) {
            $identityObject->setLoginAt(new \DateTime('now'));
        }

        $this->getMapper()->update($identityObject)->save();

        $this->setSatisfied(true);

        $storage = $this->getStorage()->read();
        $storage['identity'] = $e->getIdentity();
        $this->getStorage()->write($storage);

        $e->setCode(Result::SUCCESS)
          ->setMessages(['Authentication successful']);
    }
public function authenticate(AdapterChainEvent $e)
    {
        if ($this->isSatisfied()) {
            $storage = $this->getStorage()->read();
            $e->setIdentity($storage['identity'])
              ->setCode(Result::SUCCESS)
              ->setMessages(['Authentication successful']);

            return;
        }

        $post = $e->getRequest()->getPost();

        $identity = $post->get($e->getIdentityKey());
        $identityObject = $this->getMapper()->findByIdentity($identity);
        if (!$identityObject) {
            $e->setCode(Result::FAILURE_IDENTITY_NOT_FOUND)
              ->setMessages(['A record with the supplied identity could not be found']);
            $this->setSatisfied(false);

            return false;
        }

        if ($identityObject instanceof PasswordableInterface) {
            $credential = $post->get($e->getCredentialKey());
            $credential = $this->preprocessCredential($credential);
            $password   = $identityObject->getPassword();

            if (!$this->getMapper()->getPasswordService()->verify($credential, $password)) {
                // Password does not match
                $e->setCode(Result::FAILURE_CREDENTIAL_INVALID)
                  ->setMessages(['Supplied credential is invalid']);
                $this->setSatisfied(false);

                return false;
            }

            // Update user's password hash if the cost parameter has changed
            $this->updateCredentialHash($identityObject, $credential);
        }

        if ($identityObject instanceof StateableInterface) {
            $allowedStates = $this->options->getAllowedAuthenticationStates();

            // Don't allow user to login if state is not in allowed list
            if ($allowedStates && !in_array($identityObject->getState(), $allowedStates, true)) {
                $e->setCode(Result::FAILURE_UNCATEGORIZED)
                  ->setMessages(['A record with the supplied identity is disabled']);
                $this->setSatisfied(false);

                return false;
            }
        }

        if ($identityObject instanceof ExpirableInterface
            && null !== ($expireAt = $identityObject->getExpireAt())
            && $expireAt < new \DateTime('now')
        ) {
            $e->setCode(Result::FAILURE_UNCATEGORIZED)
              ->setMessages(['Record has expired']);
            $this->setSatisfied(false);

            return false;
        }

        // Regenerate the id
        $session = new Container($this->getStorage()->getNameSpace());
        $session->getManager()->regenerateId();

        // Success!
        $e->setIdentity($identityObject->getId());

        // Remember user if needed
        if ($post->get('rememberme') && ($ttl = $e->getRememberMeTimeout()) > 0) {
            $session->getManager()->rememberMe($ttl);
        }

        if ($identityObject instanceof LoginTrackableInterface) {
            $identityObject->setLoginAt(new \DateTime('now'));
        }

        $this->getMapper()->update($identityObject)->save();

        $this->setSatisfied(true);

        $storage = $this->getStorage()->read();
        $storage['identity'] = $e->getIdentity();
        $this->getStorage()->write($storage);

        $e->setCode(Result::SUCCESS)
          ->setMessages(['Authentication successful']);
    }
{@inheritDoc}

@throws Exception\BadMethodCallException