case 4726 - login lockout per login name and per address
Failed logins are counted in memory (util/LoginThrottle.cs): 10 per login name or 50 per client address within 15 minutes, then attempts are refused with 429 for the rest of the window without checking the password. A correct password clears the login's count; loopback is not counted per address. Each lockout is logged. F6 fixed (2FA part in case 4710). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -82,8 +82,14 @@ namespace AyaNova.Api.Controllers
|
||||
return StatusCode(451, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED, "generalerror", "License agreement consent required"));
|
||||
}
|
||||
|
||||
//case 4726: too many failed logins for this login name or from this address: refused at once, the password is not checked
|
||||
var address = HttpContext.Connection.RemoteIpAddress;
|
||||
if (LoginThrottle.IsRefused(creds.Login, address))
|
||||
return StatusCode(429, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED, null, "Too many failed login attempts, please try again later"));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(creds.Login) || string.IsNullOrWhiteSpace(creds.Password))
|
||||
{
|
||||
RecordLoginFailure(creds.Login, address);
|
||||
//Make a failed pw wait
|
||||
await Task.Delay(AyaNova.Util.ServerBootConfig.FAILED_AUTH_DELAY);
|
||||
return StatusCode(401, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED));
|
||||
@@ -99,7 +105,7 @@ namespace AyaNova.Api.Controllers
|
||||
string hashed = Hasher.hash(u.Salt, creds.Password);
|
||||
if (hashed == u.Password)
|
||||
{
|
||||
|
||||
LoginThrottle.RecordSuccess(creds.Login);
|
||||
|
||||
//TWO FACTOR ENABLED??
|
||||
//if 2fa enabled then need to validate it before sending token, so we're halfway there and need to send a 2fa prompt
|
||||
@@ -134,11 +140,20 @@ namespace AyaNova.Api.Controllers
|
||||
}
|
||||
|
||||
//No users matched, it's a failed login
|
||||
RecordLoginFailure(creds.Login, address);
|
||||
//Make a failed pw wait
|
||||
await Task.Delay(AyaNova.Util.ServerBootConfig.FAILED_AUTH_DELAY);
|
||||
return StatusCode(401, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED));
|
||||
}
|
||||
|
||||
//case 4726
|
||||
private void RecordLoginFailure(string login, System.Net.IPAddress address)
|
||||
{
|
||||
var reached = LoginThrottle.RecordFailure(login, address);
|
||||
if (reached != null)
|
||||
log.LogWarning($"Too many failed login attempts for {reached}: further attempts refused for up to 15 minutes");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user