public function validateTOTP($token)
 {
     assert(is_string($token));
     if (!$this->owner->Has2FA) {
         return true;
     }
     $seed = $this->OTPSeed();
     if (!$seed) {
         return true;
     }
     $window = (int) \Config::inst()->get(__CLASS__, 'totp_window');
     $totp = new TOTP($seed, array('window' => $window));
     $valid = $totp->validate($token);
     if (!$valid) {
         foreach ($this->owner->BackupTokens() as $bt) {
             if ($bt->Value == $token) {
                 $valid = true;
                 if ($bt::config()->single_use) {
                     $bt->delete();
                 }
             }
         }
     }
     return $valid;
 }
 public function validateTOTP($token)
 {
     assert(is_string($token));
     if (!$this->owner->Has2FA) {
         return true;
     }
     $seed = $this->OTPSeed();
     if (!$seed) {
         return true;
     }
     $window = (int) \Config::inst()->get(__CLASS__, 'totp_window');
     $totp = new TOTP($seed, array('window' => $window));
     $valid = $totp->validate($token);
     // Check backup tokens if unsuccessful
     if (!$valid) {
         $backup_tokens = $this->owner->BackupTokens()->filter('Value', $token);
         if ($backup_tokens->count()) {
             $candidate_backup_token = $backup_tokens->first();
             if ($token === $candidate_backup_token->Value) {
                 $valid = true;
                 // Backup tokens should be unique;
                 // ensure any duplicates are deleted when successfully used
                 foreach ($backup_tokens as $bt) {
                     $bt->delete();
                 }
             }
         }
     }
     return $valid;
 }
 /**
  * Validates the users two factor authentication code
  * @return boolean
  */
 private function validateTwoFactorCode()
 {
     $otpSeed = $this->getUser()->getMetadataObject('OTPSeed', false)->value;
     if ($otpSeed === false) {
         return false;
     }
     $otplib = new TOTP(Cii::decrypt($otpSeed));
     return $otplib->validate($this->twoFactorCode);
 }