diff --git a/lib/NGCP/Panel/Controller/Root.pm b/lib/NGCP/Panel/Controller/Root.pm index 389be6e1f3..fe60d6cb4f 100644 --- a/lib/NGCP/Panel/Controller/Root.pm +++ b/lib/NGCP/Panel/Controller/Root.pm @@ -526,6 +526,17 @@ sub login_jwt :Chained('/') :PathPart('login_jwt') :Args(0) :Method('POST') { return; } + my $banned = NGCP::Panel::Utils::Auth::user_is_banned($c, $user, $ngcp_realm); + if ($banned) { + my $ip = $c->request->address; + $c->response->status(HTTP_FORBIDDEN); + $c->response->body(encode_json({ + code => HTTP_FORBIDDEN, + message => "Forbidden!" })."\n"); + $c->log->debug("Banned user=$user realm=$ngcp_realm ip=$ip login attempt"); + return; + } + my $auth_user; if ($jwt) { my $realm = $ngcp_realm eq 'admin' ? 'api_admin_jwt' @@ -537,6 +548,7 @@ sub login_jwt :Chained('/') :PathPart('login_jwt') :Args(0) :Method('POST') { code => HTTP_FORBIDDEN, message => "Forbidden!" })."\n"); $c->log->info("Invalid JWT"); + NGCP::Panel::Utils::Auth::log_failed_login_attempt($c, $user, $ngcp_realm); return; } $auth_user = $c->user; @@ -561,6 +573,7 @@ sub login_jwt :Chained('/') :PathPart('login_jwt') :Args(0) :Method('POST') { code => HTTP_FORBIDDEN, message => "Forbidden!" })."\n"); $c->log->info("Unknown auth_token"); + NGCP::Panel::Utils::Auth::log_failed_login_attempt($c, $user, $ngcp_realm); return; } @@ -573,6 +586,7 @@ sub login_jwt :Chained('/') :PathPart('login_jwt') :Args(0) :Method('POST') { code => HTTP_FORBIDDEN, message => "Forbidden!" })."\n"); $c->log->info("Wrong auth_token role"); + NGCP::Panel::Utils::Auth::log_failed_login_attempt($c, $user, $ngcp_realm); return; } @@ -589,6 +603,7 @@ sub login_jwt :Chained('/') :PathPart('login_jwt') :Args(0) :Method('POST') { code => HTTP_FORBIDDEN, message => "Forbidden!" })."\n"); $c->log->info("Wrong auth_token role"); + NGCP::Panel::Utils::Auth::log_failed_login_attempt($c, $user, $ngcp_realm); return; } @@ -652,6 +667,7 @@ sub login_jwt :Chained('/') :PathPart('login_jwt') :Args(0) :Method('POST') { code => HTTP_FORBIDDEN, message => "User not found" })."\n"); $c->log->info("User not found"); + NGCP::Panel::Utils::Auth::log_failed_login_attempt($c, $user, $ngcp_realm); return; } } else { @@ -733,6 +749,7 @@ sub login_jwt :Chained('/') :PathPart('login_jwt') :Args(0) :Method('POST') { code => HTTP_FORBIDDEN, message => "User not found" })."\n"); $c->log->info("User not found"); + NGCP::Panel::Utils::Auth::log_failed_login_attempt($c, $user, $ngcp_realm); return; } $log_user = $auth_user->login; @@ -758,11 +775,13 @@ sub login_jwt :Chained('/') :PathPart('login_jwt') :Args(0) :Method('POST') { code => HTTP_FORBIDDEN, message => "User not found" })."\n"); $c->log->info("User not found"); + NGCP::Panel::Utils::Auth::log_failed_login_attempt($c, $user, $ngcp_realm); return; } $log_user = $auth_user->webusername; $log_user_id = $auth_user->uuid; } + NGCP::Panel::Utils::Auth::clear_failed_login_attempts($c, $user, $ngcp_realm); $c->log->debug(sprintf '%s JWT token for user=%s id=%s realm=%s expires_in_secs=%d', $jwt ? 'Re-issue' : 'Issue', diff --git a/lib/NGCP/Panel/Utils/Auth.pm b/lib/NGCP/Panel/Utils/Auth.pm index 4b1c7fccba..34b0116933 100644 --- a/lib/NGCP/Panel/Utils/Auth.pm +++ b/lib/NGCP/Panel/Utils/Auth.pm @@ -493,9 +493,10 @@ sub generate_auth_token { sub user_is_banned { my ($c, $user, $realm) = @_; + my $ip = $c->request->address; my $redis = $c->redis_get_connection({database => $c->config->{'Plugin::Session'}->{redis_db}}); - my $key = "login:ban:$user:$realm"; + my $key = "login:ban:$user:$realm:$ip"; return $redis->exists($key) ? 1 : 0; } @@ -506,10 +507,11 @@ sub log_failed_login_attempt { return unless $c->config->{security}{login}{ban_enable}; my $expire = $c->config->{security}{login}{ban_expire_time} // 0; my $max_attempts = $c->config->{security}{login}{max_attempts} // return; + my $ip = $c->request->address; my $redis = $c->redis_get_connection({database => $c->config->{'Plugin::Session'}->{redis_db}}); - my $key = "login:fail:$user:$realm"; + my $key = "login:fail:$user:$realm:$ip"; my $attempted = ($redis->hget($key, 'attempts') // 0) + 1; $attempted >= $max_attempts ? ban_user($c, $user, $realm) @@ -527,7 +529,8 @@ sub log_failed_login_attempt { sub clear_failed_login_attempts { my ($c, $user, $realm) = @_; - my $key = "login:fail:$user:$realm"; + my $ip = $c->request->address; + my $key = "login:fail:$user:$realm:$ip"; my $redis = $c->redis_get_connection({database => $c->config->{'Plugin::Session'}->{redis_db}}); @@ -541,10 +544,10 @@ sub ban_user { return unless $c->config->{security}{login}{ban_enable}; my $expire = $c->config->{security}{login}{ban_expire_time} // 0; - $expire = 30; + my $ip = $c->request->address; + my $key = "login:ban:$user:$realm:$ip"; - my $key = "login:ban:$user:$realm"; - $c->log->info("ban user=$user realm=$realm for $expire seconds"); + $c->log->info("Ban user=$user realm=$realm ip=$ip for $expire seconds"); my $redis = $c->redis_get_connection({database => $c->config->{'Plugin::Session'}->{redis_db}});