diff --git a/classes/config.php b/classes/config.php index f60b96f2a..6e8d4533f 100644 --- a/classes/config.php +++ b/classes/config.php @@ -167,6 +167,9 @@ class Config { const ENABLE_PLUGIN_INSTALLER = "ENABLE_PLUGIN_INSTALLER"; // allow installing first party plugins using plugin installer in prefs + const AUTH_MIN_INTERVAL = "AUTH_MIN_INTERVAL"; + // minimum amount of seconds required between authentication attempts + // default values for all of the above: private const _DEFAULTS = [ Config::DB_TYPE => [ "pgsql", Config::T_STRING ], @@ -220,6 +223,7 @@ class Config { Config::SESSION_NAME => [ "ttrss_sid", Config::T_STRING ], Config::CHECK_FOR_PLUGIN_UPDATES => [ "true", Config::T_BOOL ], Config::ENABLE_PLUGIN_INSTALLER => [ "true", Config::T_BOOL ], + Config::AUTH_MIN_INTERVAL => [ 5, Config::T_INT ], ]; private static $instance; diff --git a/plugins/auth_internal/init.php b/plugins/auth_internal/init.php index e63263a5d..0aeff117e 100644 --- a/plugins/auth_internal/init.php +++ b/plugins/auth_internal/init.php @@ -150,6 +150,32 @@ class Auth_Internal extends Auth_Base { if ($user) { + // don't throttle app passwords + if (!$service && get_schema_version() >= 145) { + + if ($user->last_auth_attempt) { + $last_auth_attempt = strtotime($user->last_auth_attempt); + + if ($last_auth_attempt && time() - $last_auth_attempt < Config::get(Config::AUTH_MIN_INTERVAL)) { + Logger::log(E_USER_NOTICE, "Too many authentication attempts for {$user->login}, throttled."); + + // start an empty session to deliver login error message + if (session_status() != PHP_SESSION_ACTIVE) + session_start(); + + $_SESSION["login_error_msg"] = "Too many authentication attempts, throttled."; + + $user->last_auth_attempt = Db::NOW(); + $user->save(); + + return false; + } + } + + $user->last_auth_attempt = Db::NOW(); + $user->save(); + } + $salt = $user['salt'] ?? ""; $login = $user['login']; $pwd_hash = $user['pwd_hash'];