/**
  * {@inheritdoc}
  */
 public function fetchToken(Request $request)
 {
     $hash = $this->extractHash($request);
     $partials = $this->getTokenPartials($hash);
     if (empty($partials)) {
         return null;
     }
     list($selector, $series, $value) = $partials;
     try {
         if (!($authToken = $this->tokenSource()->findBySelector($selector))) {
             return null;
         }
         if ($authToken->isExpired()) {
             $this->tokenSource()->deleteToken($authToken);
             return null;
         }
         //If series is incorrect - skip record (token is invalid)
         if (strcasecmp($authToken->getSeries(), $series) !== 0) {
             return null;
         }
         //If hash is incorrect - record should be deleted because series is compromised
         if (!$this->hashes->hashEquals($value, $authToken->getHashValue())) {
             $this->tokenSource()->deleteToken($authToken);
             return null;
         }
         return $authToken;
     } catch (UndefinedTokenException $e) {
         return null;
     }
 }
 /**
  * @param TokenInterface $token
  * @param int            $lifetime
  * @return bool
  */
 public function updateToken(TokenInterface $token, $lifetime)
 {
     if (get_class($token) != static::RECORD || !$token instanceof AbstractToken) {
         throw new InvalidTokenException("Only instances of " . static::RECORD . " is allowed.");
     }
     /**
      * Set new hash, new unique selector, same series.
      * Then delete old token.
      */
     $token->tokenCode = $this->generateHash();
     $token->setField('hash', $this->hashes->makeHash($token->tokenCode));
     $token->setField('selector', $this->generateSelector($token->getSelector()));
     $token->setExpiration(new \DateTime("now + {$lifetime} seconds"));
     if (!$this->save($token)) {
         throw new AuthException("Unable to save token to database");
     }
 }