refactor: separate the method of counting failed attempts
This commit is contained in:
parent
8c51ba83a4
commit
71c31c0bbb
@ -24,6 +24,7 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
|
||||
|
||||
private static string GetAuthCacheKey(string fingerprint) => $"{fingerprint}_auth_token";
|
||||
private static string GetFirstAuthCacheKey(string fingerprint) => $"{fingerprint}_auth_token_first";
|
||||
private static string GetAttemptFailedCountKey(string fingerprint) => $"{fingerprint}_login_failed";
|
||||
|
||||
private Task SetAuthTokenDataToCache(AuthToken data, CancellationToken cancellation) =>
|
||||
cache.SetAsync(
|
||||
@ -47,34 +48,47 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
|
||||
private Task RevokeAccessToken(string token) =>
|
||||
revokedToken.AddTokenToRevokedAsync(token, accessTokenService.GetExpireDateTime(token));
|
||||
|
||||
private async Task VerifyUserOrThrowError(RequestContextInfo requestContext, User user, string password, string username,
|
||||
CancellationToken cancellation = default)
|
||||
private async Task RecordFailedLoginAttempt(string fingerprint, string userId, CancellationToken cancellation)
|
||||
{
|
||||
if ((user.Email.Equals(username, StringComparison.OrdinalIgnoreCase) || user.Username.Equals(username, StringComparison.OrdinalIgnoreCase)) &&
|
||||
passwordService.VerifyPassword(password, user.Salt, user.PasswordHash))
|
||||
return;
|
||||
var failedLoginAttemptsCount = await cache.GetAsync<int?>(GetAttemptFailedCountKey(fingerprint), cancellation) ?? 1;
|
||||
var failedLoginCacheExpiration = TimeSpan.FromHours(1);
|
||||
|
||||
var failedLoginCacheName = $"{requestContext.Fingerprint}_login_failed";
|
||||
var countFailedLogin = await cache.GetAsync<int?>(failedLoginCacheName, cancellation) ?? 1;
|
||||
var cacheSaveTime = TimeSpan.FromHours(1);
|
||||
|
||||
await cache.SetAsync(failedLoginCacheName, countFailedLogin + 1, slidingExpiration: cacheSaveTime, cancellationToken: cancellation);
|
||||
|
||||
if (countFailedLogin > 5)
|
||||
if (failedLoginAttemptsCount > 5)
|
||||
{
|
||||
logger.LogWarning(
|
||||
"Multiple unsuccessful login attempts for user ID {UserId}. Attempt count: {AttemptNumber}.",
|
||||
user.Id,
|
||||
countFailedLogin);
|
||||
"Multiple unsuccessful login attempts for user ID {UserId}. Fingerprint: {Fingerprint}. Attempt count: {AttemptNumber}.",
|
||||
userId,
|
||||
fingerprint,
|
||||
failedLoginAttemptsCount);
|
||||
|
||||
throw new SecurityException("Too many unsuccessful login attempts. Please try again later.");
|
||||
}
|
||||
|
||||
logger.LogInformation(
|
||||
"Login attempt failed for user ID {UserId}. Fingerprint: {Fingerprint}. Attempt count: {AttemptNumber}.",
|
||||
user.Id,
|
||||
requestContext.Fingerprint,
|
||||
countFailedLogin);
|
||||
userId,
|
||||
fingerprint,
|
||||
failedLoginAttemptsCount);
|
||||
|
||||
await cache.SetAsync(GetAttemptFailedCountKey(fingerprint), failedLoginAttemptsCount + 1,
|
||||
slidingExpiration: failedLoginCacheExpiration, cancellationToken: cancellation);
|
||||
}
|
||||
|
||||
private Task ResetFailedLoginAttempts(string fingerprint, CancellationToken cancellation) =>
|
||||
cache.RemoveAsync(GetAttemptFailedCountKey(fingerprint), cancellation);
|
||||
|
||||
private async Task VerifyUserOrThrowError(RequestContextInfo requestContext, User user, string password, string username,
|
||||
CancellationToken cancellation = default)
|
||||
{
|
||||
if ((user.Email.Equals(username, StringComparison.OrdinalIgnoreCase) ||
|
||||
user.Username.Equals(username, StringComparison.OrdinalIgnoreCase)) &&
|
||||
passwordService.VerifyPassword(password, user.Salt, user.PasswordHash))
|
||||
{
|
||||
await ResetFailedLoginAttempts(requestContext.Fingerprint, cancellation);
|
||||
return;
|
||||
}
|
||||
|
||||
await RecordFailedLoginAttempt(requestContext.Fingerprint, user.Id, cancellation);
|
||||
|
||||
throw new SecurityException("Authentication failed. Please check your credentials.");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user