2fa code attempts period separate param

This commit is contained in:
Yuri Kuznetsov
2024-06-27 10:34:55 +03:00
parent a89860dc52
commit 6f00a6b2e7
3 changed files with 30 additions and 18 deletions

View File

@@ -37,6 +37,7 @@ use Espo\Core\Utils\Metadata;
class ConfigDataProvider
{
private const FAILED_ATTEMPTS_PERIOD = '60 seconds';
private const FAILED_CODE_ATTEMPTS_PERIOD = '5 minutes';
private const MAX_FAILED_ATTEMPT_NUMBER = 10;
public function __construct(private Config $config, private Metadata $metadata)
@@ -50,6 +51,14 @@ class ConfigDataProvider
return $this->config->get('authFailedAttemptsPeriod', self::FAILED_ATTEMPTS_PERIOD);
}
/**
* A period for max failed 2FA code attempts checking.
*/
public function getFailedCodeAttemptsPeriod(): string
{
return $this->config->get('authFailedCodeAttemptsPeriod', self::FAILED_CODE_ATTEMPTS_PERIOD);
}
/**
* Max failed log in attempts.
*/

View File

@@ -61,32 +61,20 @@ class FailedAttemptsLimit implements BeforeLogin
{
$isByTokenOnly = !$data->getMethod() && $request->getHeader(HeaderKey::AUTHORIZATION_BY_TOKEN) === 'true';
if ($isByTokenOnly) {
return;
}
if ($this->configDataProvider->isAuthLogDisabled()) {
if ($isByTokenOnly || $this->configDataProvider->isAuthLogDisabled()) {
return;
}
$isSecondStep = $request->getHeader(HeaderKey::AUTHORIZATION_CODE) !== null;
$failedAttemptsPeriod = $this->configDataProvider->getFailedAttemptsPeriod();
$maxFailedAttempts = $this->configDataProvider->getMaxFailedAttemptNumber();
$requestTime = intval($request->getServerParam('REQUEST_TIME_FLOAT'));
try {
$requestTimeFrom = (new DateTime('@' . $requestTime))->modify('-' . $failedAttemptsPeriod);
}
catch (Exception $e) {
throw new RuntimeException($e->getMessage());
}
$failedAttemptsPeriod = $isSecondStep ?
$this->configDataProvider->getFailedCodeAttemptsPeriod() :
$this->configDataProvider->getFailedAttemptsPeriod();
$ipAddress = $this->util->obtainIpFromRequest($request);
$where = [
'requestTime>' => $requestTimeFrom->format('U'),
'requestTime>' => $this->getTimeFrom($request, $failedAttemptsPeriod)->format('U'),
'isDenied' => true,
];
@@ -113,7 +101,7 @@ class FailedAttemptsLimit implements BeforeLogin
->where($where)
->count();
if ($failAttemptCount <= $maxFailedAttempts) {
if ($failAttemptCount <= $this->configDataProvider->getMaxFailedAttemptNumber()) {
return;
}
@@ -125,4 +113,18 @@ class FailedAttemptsLimit implements BeforeLogin
throw new Forbidden("Max failed login attempts exceeded for IP address $ipAddress.");
}
private function getTimeFrom(Request $request, string $failedAttemptsPeriod): DateTime
{
$requestTime = intval($request->getServerParam('REQUEST_TIME_FLOAT'));
try {
$requestTimeFrom = (new DateTime('@' . $requestTime))->modify('-' . $failedAttemptsPeriod);
}
catch (Exception $e) {
throw new RuntimeException($e->getMessage());
}
return $requestTimeFrom;
}
}

View File

@@ -104,6 +104,7 @@ return [
'authLogDisabled',
'authApiUserLogDisabled',
'authFailedAttemptsPeriod',
'authFailedCodeAttemptsPeriod',
'authMaxFailedAttemptNumber',
'ipAddressServerParam',
'jobNoTableLocking',