using System.Net.Mime; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using OpenWarehouse.auth.api.Common.AuthTokenRepo; using OpenWarehouse.auth.api.Common.CustomIdentifyManager; using OpenWarehouse.auth.api.Common.RegisterTokenManager; using OpenWarehouse.auth.lib.Model.Account; using OpenWarehouse.auth.lib.Model.Auth; namespace OpenWarehouse.auth.api.Controller; [ApiController] [Route("[action]")] public class Auth( SignInManager signInManager, UserManager userManager, AuthTokenRepo tokenRepo, ApplicationDbContext applicationDbContext, RegisterTokenManager registerTokenManager, ILogger logger) : ControllerBase { [HttpPost] [Consumes(MediaTypeNames.Application.Json, MediaTypeNames.Application.Xml)] public async Task> Login([FromBody] LoginRequestModel requestModel) { logger.LogInformation("Login request received for user: {Login}", requestModel.Login); if (requestModel.Pass == null || requestModel.Login == null) { logger.LogWarning("Invalid login request model."); return BadRequest("Invalid request model."); } var loginModel = new LoginModel(); if (requestModel.Pass == null) { loginModel.AccountProblem = "Login and password are required."; logger.LogWarning("Password is missing in the login request for user: {Login}", requestModel.Login); return BadRequest(loginModel); } var applicationUser = await userManager.FindByNameAsync(requestModel.Login) ?? await userManager.FindByEmailAsync(requestModel.Login); if (applicationUser == null) { logger.LogWarning("User not found for login: {Login}", requestModel.Login); loginModel.Message = "Incorrect login or password."; return Unauthorized(loginModel); } loginModel.Login = applicationUser.UserName; loginModel.Email = applicationUser.Email; var claims = await userManager.GetClaimsAsync(applicationUser); if (claims.Any(claim => claim.Type.Equals(AccountType.Service.GetValue()))) { logger.LogWarning("Service account attempted to login: {Login}", requestModel.Login); return Forbid("This is a service account."); } if (applicationUser.LockoutEnabled) { logger.LogWarning("Locked account attempted to login: {Login}", requestModel.Login); return Forbid("Account is locked."); } var signInResult = await signInManager.CheckPasswordSignInAsync(applicationUser, requestModel.Pass, false); if (signInResult.Succeeded) { // var expiration = DateTime.UtcNow.AddHours(1); var expiration = DateTime.UtcNow.AddMinutes(30); loginModel.Token = await tokenRepo.CreateJwtToken(applicationUser, expiration, null); loginModel.Exp = expiration.ToBinary(); loginModel.IsLogged = true; logger.LogInformation("User logged in successfully: {Login}", requestModel.Login); return Ok(loginModel); } if (signInResult.RequiresTwoFactor) { logger.LogInformation("Two-factor authentication required for user: {Login}", requestModel.Login); loginModel.Message = "Two-factor authentication is required."; loginModel.RequiresTwoFactor = true; return Ok(loginModel); } logger.LogWarning("Incorrect login or password for user: {Login}", requestModel.Login); loginModel.Message = "Incorrect login or password."; return Unauthorized(loginModel); } [HttpPost] [Consumes(MediaTypeNames.Application.Json, otherContentTypes: [MediaTypeNames.Application.Xml])] public async Task> Register([FromBody]RegisterModel registerModel) { logger.LogInformation("Registration request received for user: {Username}", registerModel.Username); var registerReturnModel = new RegisterReturnModel(); registerReturnModel.IsCreated = true; if (registerModel.Username != null) { var user = new ApplicationUser(registerModel.Username); user.Email = registerModel.Email; if (registerModel.RegisterToken != null) { var regToken = await registerTokenManager.GetToken(registerModel.RegisterToken); if (regToken == null) { logger.LogWarning("Registration token not found: {RegisterToken}", registerModel.RegisterToken); registerReturnModel.IsCreated = false; registerReturnModel.ProblemWithToken = "Token Not found;"; return Unauthorized(registerReturnModel); } if (regToken.IsUsed) { logger.LogWarning("Registration token already used: {RegisterToken}", registerModel.RegisterToken); registerReturnModel.IsCreated = false; registerReturnModel.ProblemWithToken = "Token is alleredy used;"; } if (( registerModel.Password ?? "" ).Length > 6) { registerReturnModel.IsCreated = false; } if (!registerReturnModel.IsCreated) return Unauthorized(registerReturnModel); if (registerModel.Password != null) { var result = await userManager.CreateAsync(user, registerModel.Password); var resultClaim = await userManager.AddClaimAsync(user, AccountType.User.Claim()); if (result.Succeeded && resultClaim.Succeeded) { regToken.IsUsed = true; await applicationDbContext.SaveChangesAsync(); registerReturnModel.AuthToken = await tokenRepo.CreateJwtToken(user, DateTime.UtcNow.AddHours(1), null); logger.LogInformation("User registered successfully: {Username}", registerModel.Username); } else { foreach (var error in result.Errors) { logger.LogError("Error during user registration: {Code} - {Description}", error.Code, error.Description); registerReturnModel.OtherWithOtherProblem += error.Code + "-" + error.Description + ";"; return Unauthorized(registerReturnModel); } } } } else { logger.LogWarning("Registration token is required but missing for user: {Username}", registerModel.Username); return BadRequest("Token are required."); } } return Ok(registerReturnModel); } [HttpGet] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public async Task LogOut() { logger.LogInformation("Logout request received."); if (Request.Headers.TryGetValue("Authorization", out var token)) { var tokenStr = token.ToString(); string?[] tokenSplit = tokenStr.Split(" "); if (tokenSplit.Length > 0) tokenStr = tokenSplit[1]; if (await tokenRepo.LockTokenAsync(tokenStr) > 0) { logger.LogInformation("User logged out successfully."); return new LogOutModel(true, "Logout successful"); } } logger.LogWarning("Logout failed due to missing or invalid token."); return new LogOutModel(false, "Logout Fail"); } [HttpGet] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public async Task> RegenerateToken() { logger.LogInformation("Token regeneration request received."); Request.Headers.TryGetValue("Authorization", out var token); token = token.ToString().Split(" ")[1]; var newTokenStr = await tokenRepo.RegenerateJwtToken(token, DateTime.UtcNow.AddMinutes(30)); logger.LogInformation("Token regenerated successfully"); var respond = new RegeneratedTokenModel() { Mess = newTokenStr != null ? "Regeneration success" : "Regeneration fail", Token = newTokenStr }; return Ok(respond); } [HttpDelete] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] [HasPrivilege(GlobalPrivilage.Privilege.GlobalDeleteExpiredToken)] public async Task> DeleteExpiredToken() { logger.LogInformation("Delete expired tokens request received."); return Ok(await tokenRepo.DeleteInactiveToken()); } [HttpPost] public async Task> TokenIsLock([FromBody] TokenAskIfIsLockModel req) { logger.LogInformation("Check if token is locked request received."); return Ok(await tokenRepo.IsTokenLockAsync(req.Token)); } }