From 1a1fd09b1b295090ce01b154e32bf66e2dcd705e Mon Sep 17 00:00:00 2001 From: emrecoskun705 Date: Sun, 10 Sep 2023 17:06:38 +0300 Subject: [PATCH] add user lockout after given retry count --- .../IdentityServiceRegistration.cs | 3 ++ Unitagram.Identity/Models/Confirmation.cs | 6 ++++ .../SixDigitEmailConfirmationTokenProvider.cs | 2 +- Unitagram.Identity/Services/AuthService.cs | 28 ++++++++++++++++++- Unitagram.WebAPI/api.xml | 2 +- 5 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 Unitagram.Identity/Models/Confirmation.cs diff --git a/Unitagram.Identity/IdentityServiceRegistration.cs b/Unitagram.Identity/IdentityServiceRegistration.cs index 392f623..ab5c6ad 100644 --- a/Unitagram.Identity/IdentityServiceRegistration.cs +++ b/Unitagram.Identity/IdentityServiceRegistration.cs @@ -34,6 +34,9 @@ public static IServiceCollection AddIdentityServices(this IServiceCollection ser options.Password.RequireUppercase = true; options.Password.RequireLowercase = true; + options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(3); // Lockout duration (3 minutes) + options.Lockout.MaxFailedAccessAttempts = 8; // Maximum failed attempts before lockout (8 attempts) + options.SignIn.RequireConfirmedEmail = true; options.Tokens.EmailConfirmationTokenProvider = "emailconfirmation"; }) diff --git a/Unitagram.Identity/Models/Confirmation.cs b/Unitagram.Identity/Models/Confirmation.cs new file mode 100644 index 0000000..3319184 --- /dev/null +++ b/Unitagram.Identity/Models/Confirmation.cs @@ -0,0 +1,6 @@ +namespace Unitagram.Identity.Models; + +public class Confirmation +{ + +} \ No newline at end of file diff --git a/Unitagram.Identity/Providers/SixDigitEmailConfirmationTokenProvider.cs b/Unitagram.Identity/Providers/SixDigitEmailConfirmationTokenProvider.cs index 0432b2b..b10da0f 100644 --- a/Unitagram.Identity/Providers/SixDigitEmailConfirmationTokenProvider.cs +++ b/Unitagram.Identity/Providers/SixDigitEmailConfirmationTokenProvider.cs @@ -26,7 +26,7 @@ public override Task GenerateAsync(string purpose, UserManager ma { throw new ArgumentNullException(nameof(manager)); } - + var code = GenerateRandom6DigitCode(); // Generate a 6-digit code as a string return Task.FromResult(code); } diff --git a/Unitagram.Identity/Services/AuthService.cs b/Unitagram.Identity/Services/AuthService.cs index ce529a7..2691452 100644 --- a/Unitagram.Identity/Services/AuthService.cs +++ b/Unitagram.Identity/Services/AuthService.cs @@ -62,9 +62,25 @@ public async Task> Login(AuthRequest request) return new Result(notFoundException); } + if (user.LockoutEnabled && user.AccessFailedCount >= _userManager.Options.Lockout.MaxFailedAccessAttempts-1) + { + var lockoutEndDate = await _userManager.GetLockoutEndDateAsync(user); + if (lockoutEndDate >= DateTimeOffset.UtcNow) + { + var lockoutException = new BadRequestException($"Account locked out. Try again later."); + return new Result(lockoutException); + } + else + { + // If lockout has expired, reset the AccessFailedCount and LockoutEnd + await _userManager.ResetAccessFailedCountAsync(user); + await _userManager.SetLockoutEndDateAsync(user, null); // Reset lockout end date + } + } + if (!user.EmailConfirmed) { - var badRequestException = new BadRequestException($"Email is not confirmed for '{request.UserName}'."); + var badRequestException = new BadRequestException($"Email is not confirmed for '{user.Email}'."); return new Result(badRequestException); } @@ -72,9 +88,19 @@ public async Task> Login(AuthRequest request) if (result.Succeeded == false) { + await _userManager.AccessFailedAsync(user); + if (user.LockoutEnabled && user.AccessFailedCount >= _userManager.Options.Lockout.MaxFailedAccessAttempts-1) + { + await _userManager.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow.Add(_userManager.Options.Lockout.DefaultLockoutTimeSpan)); + var lockoutException = new BadRequestException($"Account locked out. Try again later."); + return new Result(lockoutException); + } + var badRequestException = new BadRequestException($"Credentials for '{request.UserName} aren't valid'."); return new Result(badRequestException); } + + await _signInManager.SignInAsync(user, false); JwtResponse jwtResponse = _jwtService.CreateJwtToken(await UserToJwtRequest(user)); // update user diff --git a/Unitagram.WebAPI/api.xml b/Unitagram.WebAPI/api.xml index 741f485..e072399 100644 --- a/Unitagram.WebAPI/api.xml +++ b/Unitagram.WebAPI/api.xml @@ -28,7 +28,7 @@ Controller responsible for user account-related actions. - + Initializes a new instance of the class.