/** * Most complex method, can check everything:-) * ToDo: describe after refactoring * * @param array $params * @throws ArgumentTypeException * @return bool */ public static function verifyUser(array $params) { /** @global \CMain $APPLICATION */ global $APPLICATION; if (!static::isOtpEnabled()) { // OTP disabled in settings return true; } $isSuccess = false; // ToDo: review and refactoring needed $otp = static::getByUser($params['USER_ID']); if (!$otp->isActivated()) { // User does not use OTP $isSuccess = true; if (static::isMandatoryUsing() && !$otp->canSkipMandatory()) { // Grace full period ends. We must reject authorization and defer reject reason if (!$otp->isDbRecordExists() && static::getSkipMandatoryDays()) { // If mandatory enabled and user never use OTP - let's deffer initialization $otp->defer(static::getSkipMandatoryDays()); // We forgive the user for the first time static::setDeferredParams(null); return true; } // Save a flag which indicates that a OTP is required, but user doesn't use it :-( $params[static::REJECTED_KEY] = static::REJECT_BY_MANDATORY; static::setDeferredParams($params); return false; } } if (!$isSuccess) { // User skip OTP on this browser by cookie $isSuccess = $otp->canSkipByCookie(); } if (!$isSuccess) { $isCaptchaChecked = !$otp->isAttemptsReached() || $APPLICATION->captchaCheckCode($params['CAPTCHA_WORD'], $params['CAPTCHA_SID']); $isRememberNeeded = $params['OTP_REMEMBER'] && Option::get('security', 'otp_allow_remember') === 'Y'; if (!$isCaptchaChecked && !$_SESSION['BX_LOGIN_NEED_CAPTCHA']) { // Backward compatibility with old login page $_SESSION['BX_LOGIN_NEED_CAPTCHA'] = true; } $isOtpPassword = (bool) preg_match('/^\\d{6}$/D', $params['OTP']); $isRecoveryCode = static::isRecoveryCodesEnabled() && (bool) preg_match(RecoveryCodesTable::CODE_PATTERN, $params['OTP']); if ($isCaptchaChecked && ($isOtpPassword || $isRecoveryCode)) { if ($isOtpPassword) { $isSuccess = $otp->verify($params['OTP'], true); } elseif ($isRecoveryCode) { $isSuccess = RecoveryCodesTable::useCode($otp->getUserId(), $params['OTP']); } else { $isSuccess = false; } if (!$isSuccess) { $otp->setAttempts($otp->getAttempts() + 1)->save(); } else { if ($otp->getAttempts() > 0) { // Clear OTP input attempts $otp->setAttempts(0)->save(); } if ($isRememberNeeded && $isOtpPassword) { // If user provide otp password (not recovery codes) // Sets cookie for bypass OTP checking $otp->setSkipCookie(); } } } } if ($isSuccess) { static::setDeferredParams(null); } else { // Save a flag which indicates that a form for OTP is required $params[static::REJECTED_KEY] = static::REJECT_BY_CODE; static::setDeferredParams($params); } return $isSuccess; }