using LdapLoginLib; using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.Tokens; using MSAdminUsuarios.Context; using Newtonsoft.Json.Linq; using Security; using System.IdentityModel.Tokens.Jwt; using System.Reflection.Metadata; using System.Security.Claims; using System.Text; namespace MSAdminUsuarios.Controllers { [ApiController] [Route("[controller]")] public class AuthController : ControllerBase { private readonly ModelContext _context; private readonly Encripter _encript = new(); private readonly LDAP _ldap; public AuthController(ModelContext context) { _context = context; var loggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); }); var logger = loggerFactory.CreateLogger(); _ldap = new LDAP(logger); } [HttpPost("Login")] public IActionResult Login([FromBody] LoginModel login) { try { if (!_encript.IsValid) return BadRequest("Lectura inválida"); if (login.TX_LOGINNAME_USUMS == null) return BadRequest("Es necesario ingresar un usuario"); if ( string.IsNullOrEmpty(login.TX_LOGINNAME_USUMS?.Trim()) && string.IsNullOrEmpty(login.TX_PKDOC_USUMS?.Trim()) && string.IsNullOrEmpty(login.TX_CORREO_USUMS?.Trim()) ) { throw new Exception("Es necesario ingresar un usuario."); } if (login.TX_PASSWORD_USUMS == null) return BadRequest("Es necesario ingresar una contraseña."); USUARIO? userldap = _context.USUARIOSMs.FirstOrDefault(u => u.TX_LOGINNAME_USUMS == login.TX_LOGINNAME_USUMS); if (userldap == null) return BadRequest("Nombre de usuario no encontrado."); if (userldap.NU_ESTADO_USUMS != 1) return BadRequest("Usuarios inactivo o bloqueado."); if (userldap.BL_VIENELDAP_USUMS == 1) { //bool boolldap = LoginLib.Login(login.TX_LOGINNAME_USUMS, login.TX_PASSWORD_USUMS); bool loggedWithLdap = _ldap.Login( username: login.TX_LOGINNAME_USUMS, document: login.TX_PKDOC_USUMS, email: login.TX_CORREO_USUMS, password: login.TX_PASSWORD_USUMS ); if (loggedWithLdap == true) { string token = Token(userldap); return Ok(new { token = token, user = userldap.TX_PKDOC_USUMS }); } else { return BadRequest(); } }else if(userldap.BL_VIENELDAP_USUMS != 1) { USUARIO? user = _context.USUARIOSMs.FirstOrDefault(u => u.TX_LOGINNAME_USUMS == login.TX_LOGINNAME_USUMS && u.TX_PASSWORD_USUMS == _encript.EncryptPwd(login.TX_PASSWORD_USUMS)); if (user == null) return BadRequest("Usuario o contraseña incorrectos"); string token = Token(user); return Ok(new { token = token, user = user.TX_PKDOC_USUMS }); }else { return BadRequest("Error"); } } catch (Exception e) { return BadRequest(e.Message); } } [HttpPost("CambiarClave")] public IActionResult CambiarClave([FromBody] USUARIO us) { try { USUARIO? user = _context.USUARIOSMs.FirstOrDefault(u => us.NU_PK_USUMS == u.NU_PK_USUMS); if (user == null) return BadRequest("Usuario no encontrado."); string newPass = _encript.EncryptPwd(us.TX_PASSWORD_USUMS!); user.TX_PASSWORD_USUMS = newPass; _context.USUARIOSMs.Update(user); _context.SaveChanges(); return Ok("Contrase�a actualizada correctamente"); } catch (Exception e) { return Conflict(e.Message); } } [HttpPost("Proveedor")] public IActionResult LoginProveedores([FromBody] LoginModel login) { try { if (!_encript.IsValid) return BadRequest(new ResLoginExt("Lectura inv�lida")); if (login.TX_LOGINNAME_USUMS == null) return BadRequest(new ResLoginExt("Es necesario ingresar un usuario")); if (login.TX_PASSWORD_USUMS == null) return BadRequest(new ResLoginExt("Es necesario ingresar una contrase�a")); USUARIO? userExist = _context.USUARIOSMs.FirstOrDefault(u => u.TX_LOGINNAME_USUMS == login.TX_LOGINNAME_USUMS); if (userExist == null) return BadRequest(new ResLoginExt("Usuario o contrase�a incorrectos")); USUARIO? user = _context.USUARIOSMs.FirstOrDefault(u => u.TX_LOGINNAME_USUMS == login.TX_LOGINNAME_USUMS && u.TX_PASSWORD_USUMS == _encript.EncryptPwd(login.TX_PASSWORD_USUMS)); if (user == null) return BadRequest(new ResLoginExt("Usuario o contrase�a incorrectos", true, userExist.NU_ESTADO_USUMS)); if (user.NU_ESTADO_USUMS != 1) return BadRequest(new ResLoginExt("Usuario inactivo o eliminado.", true, user.NU_ESTADO_USUMS)); string token = Token(user); return Ok(new ResLoginExt("Bienvenido al sistema.", true, user.NU_ESTADO_USUMS, token)); } catch (Exception e) { return BadRequest(e.Message); } } [HttpPatch("RenovarToken")] public IActionResult RefreshToken([FromBody] string token) { try { #warning este metodo se debe revisar, des-encriptado no se debe permitir! JwtSecurityTokenHandler handler = new(); JwtSecurityToken tkn = handler.ReadJwtToken(Encripter.Descypher(token)); int pk = Int32.Parse(tkn.Claims.FirstOrDefault(c => c.Type == "pk").Value); USUARIO? user = _context.USUARIOSMs.FirstOrDefault(u => u.NU_PK_USUMS == pk); if (user == null) return BadRequest("No se encuentra usuario"); string newToken = Token(user); return Ok(newToken); } catch(Exception ex) { return BadRequest(ex.Message); } } [HttpGet("Encriptar")] public IActionResult Encriptar(string text, int tipo) { if (!_encript.IsValid) return BadRequest("Lectura inv�lida"); if (tipo == 0) return Ok(_encript.EncryptPwd(text)); return Ok(_encript.EncryptHashTkn(text)); } [HttpGet("Desencriptar")] public IActionResult Desencriptar(string text, int tipo) { if (!_encript.IsValid) return BadRequest("Lectura inv�lida"); if (tipo == 0) return Ok(_encript.DecryptPwd(text)); return Ok(_encript.DecryptHashTkn(text)); } [HttpGet("TknCambioClave")] public IActionResult ObtenerTokenCambioClave(int pkUs) { try { return Ok(TokenCambioClave(pkUs)); } catch (Exception e) { return BadRequest(e.Message); } } [HttpPost("pruebaUsuario")] public string Token(USUARIO user) { List perfilesPorUsuario = (from perf in _context.PERFILESPORUSUARIOs where perf.TX_FKDOC_USUMS == user.TX_PKDOC_USUMS && perf.NU_FK_PFL != null && perf.BL_ESTADO_PFLXUSU == 1 select perf).ToList(); List perfiles = perfilesPorUsuario.Select(p => p.NU_FK_PFL).ToList(); List permisos = (from perfXUs in perfilesPorUsuario join perm in _context.PERMISOSMs on perfXUs.NU_FK_PFL equals perm.NU_FK_PFL where perm.BL_ESTADO_PMS == 1 select perm).ToList(); Dictionary perfilesPorPermiso = new(); foreach (PERMISO p in permisos) { string key = p.NU_FK_MS.ToString(); string val = p.NU_FK_PFL.ToString(); if (perfilesPorPermiso.ContainsKey(key)) { string antVal = perfilesPorPermiso[key]; perfilesPorPermiso.Remove(key); perfilesPorPermiso.Add(key, antVal + "," + val); } else { perfilesPorPermiso.Add(key, val); } } perfiles.Add(-1); //Security key debe ser un environment variable seguro var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Encripter.HashKey)); var signingCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256); string nombres = ""; string apellidos = ""; if (user.TX_PRIMERNOM_USUMS != null) nombres += user.TX_PRIMERNOM_USUMS; if (user.TX_SEGUNDONOM_USUMS != null) nombres += " " + user.TX_SEGUNDONOM_USUMS; if (user.TX_PRIMERAPELL_USUMS != null) apellidos += user.TX_PRIMERAPELL_USUMS; if (user.TX_SEGUNDOAPELL_USUMS != null) apellidos += " " + user.TX_SEGUNDOAPELL_USUMS; nombres = nombres.Trim(); apellidos = apellidos.Trim(); if (nombres == "") nombres = "N"; if (apellidos == "") apellidos = "A"; int tipo_doc = user.NU_TIPODOC_USUMS == null ? -1 : (int)user.NU_TIPODOC_USUMS; ClaimsIdentity claims = new ClaimsIdentity(new List { new Claim("user", user.TX_PKDOC_USUMS), new Claim("nombres", nombres), new Claim("apellidos", apellidos), new Claim("tipo_doc", tipo_doc.ToString()), new Claim("pk", user.NU_PK_USUMS.ToString()), new Claim("sedes", user.TX_SEDES_USUMS == null ? "" : user.TX_SEDES_USUMS), new Claim("TX_NOMBRE_PVD", user.TX_NOMBRE_PVD ?? "{}"), new Claim("uid", user.TX_UUID_USUMS.ToString()) }); foreach (int p in perfiles) { claims.AddClaim(new Claim("perfiles", p.ToString(), ClaimValueTypes.String)); } //foreach (PERMISO p in permisos) //{ // claims.AddClaim(new Claim("permisos", Encripter.Encrypt(p.NU_FK_MS.ToString()))); //} foreach (KeyValuePair p in perfilesPorPermiso) { string key = p.Key; string val = p.Value; claims.AddClaim(new Claim("permisos", _encript.EncryptHashTkn(key) + "::" + val)); } var securityTokenDescriptor = new SecurityTokenDescriptor { Subject = claims, Expires = DateTime.Now.AddDays(20), SigningCredentials = signingCredentials }; var jwtSecurityTokenHandler = new JwtSecurityTokenHandler(); var securityToken = jwtSecurityTokenHandler.CreateToken(securityTokenDescriptor); var token = jwtSecurityTokenHandler.WriteToken(securityToken); return Encripter.Cypher(token); } [HttpPatch("BloquearUsuario")] public IActionResult BloquearUsuario([FromBody] string usuario) { try { if (usuario == null) throw new Exception("Usuario no encontrado"); USUARIO? user = _context.USUARIOSMs.FirstOrDefault(u => u.TX_LOGINNAME_USUMS == usuario); if (user == null) throw new Exception("Usuario no encontrado"); user.NU_BLOQUEO_USUMS = 0; user.NU_ESTADO_USUMS = 2; _context.USUARIOSMs.Update(user); _context.SaveChanges(); return Ok(new { message = "Su cuenta ha sido bloqueada debido a demasiados intentos fallidos" }); } catch (Exception ex) { return BadRequest(new { message = ex.Message }); } } string TokenCambioClave(int pkUser) { USUARIO? user = _context.USUARIOSMs.FirstOrDefault(u => pkUser == u.NU_PK_USUMS); if (user == null) throw new Exception("Usuario no encontrado"); //Security key debe ser un environment variable seguro var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Encripter.HashKey)); var signingCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256); ClaimsIdentity claims = new ClaimsIdentity(new List { new Claim("user", user.TX_PKDOC_USUMS), new Claim("loginName", user.TX_LOGINNAME_USUMS), new Claim("pk", user.NU_PK_USUMS.ToString()) }); var securityTokenDescriptor = new SecurityTokenDescriptor { Subject = claims, Expires = DateTime.UtcNow.AddMinutes(20), SigningCredentials = signingCredentials }; var jwtSecurityTokenHandler = new JwtSecurityTokenHandler(); var securityToken = jwtSecurityTokenHandler.CreateToken(securityTokenDescriptor); var token = jwtSecurityTokenHandler.WriteToken(securityToken); return Encripter.Cypher(token); } } public class LoginModel { public string? TX_LOGINNAME_USUMS { get; set; } public string? TX_CORREO_USUMS { get; set; } public string? TX_PKDOC_USUMS { get; set; } public string? TX_PASSWORD_USUMS { get; set; } } public class ResLoginExt { public ResLoginExt(string _message, bool _exist = false, int? _estado = null, string? _token = "") { Message = _message; Token = _token; Existe = _exist; Estado = _estado; } public bool Existe { get; set; } public int? Estado { get; set; } public string? Token { get; set; } public string Message { get; set; } = null!; } static class Options { } }