- Модуль: security
- Путь к файлу: ~/bitrix/modules/security/lib/mfa/otp.php
- Класс: BitrixSecurityMfaOtp
- Вызов: Otp::verifyUser
static function verifyUser(array $params)
{
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;
}
}
else
{
if (!$otp->isUserActive())
{
//non-active user can't login by OTP
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 && !$APPLICATION->NeedCAPTHA())
{
// Backward compatibility with old login page
$APPLICATION->SetNeedCAPTHA(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);
//the OTP form will be shown on the next hit, send the event
static::sendEvent($otp);
//write to the log ("on" by default)
if(Option::get("security", "otp_log") <> "N")
{
CSecurityEvent::getInstance()->doLog("SECURITY", "SECURITY_OTP", $otp->getUserId(), "");
}
}
return $isSuccess;
}