using Microsoft.IdentityModel.Tokens; using Ocelot.Configuration; using Ocelot.Middleware; using Security; using System.IdentityModel.Tokens.Jwt; using System.IO; using System.Security.Claims; using System.Security.Policy; using System.Text; using System.Text.RegularExpressions; namespace ApiGateway { public static class CustomLogic { //private static readonly int _SEMILLA = 1262; private static readonly Encripter _encript = new(); public static bool Authorize(HttpContext ctx) { // Solo para test //string seguimiento = ctx.Request.Headers["Potato"]; //var route2 = ctx.Items.DownstreamRequest(); //Solo el path del request //var route3 = ctx.Items.DownstreamRoute(); //Datos full del request //var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().AddEventLog()); //var logger = loggerFactory.CreateLogger("Auth"); //TODO: ELIMINAR ESTAS RUTAS POR COMPLETO! // TknCambioClave // Desencriptar - encriptar string calledUrl = ctx.Items.DownstreamRoute().UpstreamPathTemplate.OriginalValue; // Excepcion para login, no requiere token if (String.Equals(calledUrl, "/Ext/Login") || String.Equals(calledUrl, "/Auth/Login") || String.Equals(calledUrl, "/Auth/CambiarClave") || String.Equals(calledUrl, "/Auth/TknCambioClave") || String.Equals(calledUrl, "/Auth/Proveedor") || String.Equals(calledUrl, "/Email") ) return true; try { //string path = ctx.Request.Path; string authString = ctx.Request.Headers["Authorization"]; //Perfil seleccionado, no obligatorio para login string? signature = ctx.Request.Headers["Signature"]; signature = Base64Decode(signature); if (String.IsNullOrEmpty(authString)) throw new Exception("No se encontró una sesión activa. Por favor inicie sesión de nuevo."); // string? jwtDescifrado = DesCifrar(authString.Replace("Bearer ", "")); if (String.IsNullOrEmpty(jwtDescifrado)) throw new Exception("La sesión es inválida. Por favor inicie sesión de nuevo. 0"); //Token invalido (firma invalida) var jwtToken = new JwtSecurityToken(jwtDescifrado); if (VerifyToken(jwtToken.RawData) == false) throw new Exception("La sesión es inválida. Por favor inicie sesión de nuevo. 1"); //Claims dentro del .json DownstreamRoute? route = (DownstreamRoute?)ctx.Items["DownstreamRoute"]; // Si no hay claims (requerimiento de Permisos) permite pasar sin problemas if (route == null || route.RouteClaimsRequirement.Count == 0) return true; //Claims del token Claim[] claims = jwtToken.Claims.ToArray(); //where are stored the required claims for the route Dictionary required = route.RouteClaimsRequirement; Regex reor = new Regex(@"[^,\s+$ ][^\,]*[^,\s+$ ]"); MatchCollection matches; Regex reand = new Regex(@"[^&\s+$ ][^\&]*[^&\s+$ ]"); MatchCollection matchesand; //int cont = 0; foreach (KeyValuePair claim in required) { matches = reor.Matches(claim.Value); foreach (Match match in matches) { matchesand = reand.Matches(match.Value); //cont = 0; foreach (Match m in matchesand) //m = claim dentro dle json (value) { //Si permite cualquier permiso if (String.Equals("any", m.Value)) return true; foreach (Claim cl in claims) // Claim (key:value) desde el token { if (cl.Type == claim.Key && String.Equals(claim.Key, "permisos")) { string separador = "::"; int index = cl.Value.LastIndexOf(separador); string newPermiso = cl.Value; string permisoRoles = cl.Value; if (index >= 0) newPermiso = cl.Value[..index]; permisoRoles = cl.Value.Substring(index + separador.Length); var rolesLst = permisoRoles.Split(','); // Excepcion de rol Seleccionado para Externo if(String.Equals(newPermiso, m.Value) && String.Equals(_encript.DecryptHashTkn(newPermiso), "externo")) { return true; } //Si no hay perfil seleccionado if (String.IsNullOrEmpty(signature)) throw new Exception("Debe seleccionar un perfil para acceder a esta información."); bool aplicaRolSeleccionado = rolesLst.Any(signature!.Contains); //Aqui remuevo los :: teniendo en cuenta key == permisos cl.Value if (String.Equals(newPermiso, m.Value) && aplicaRolSeleccionado == true) { return true; } } } } } } return false; } catch (Exception e) { //logger.LogError(71, e.Message); ctx.Items.SetError(new UnauthenticatedError(e.Message)); return false; } } public static bool VerifyToken(string token) { if(_encript.IsValid == false) return false; //var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().AddEventLog()); //var logger = loggerFactory.CreateLogger("VerifyToken"); var sb = new StringBuilder() .AppendLine("Error en: VerifyToken"); var validationParameters = new TokenValidationParameters() { ValidateIssuer = false, ValidateAudience = false, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Encripter.HashKey!)) }; var tokenHandler = new JwtSecurityTokenHandler(); SecurityToken? validatedToken = null; try { tokenHandler.ValidateToken(token, validationParameters, out validatedToken); } catch (SecurityTokenException se) { sb.AppendLine("SecurityTokenException"); sb.AppendLine(se.Message); //logger.LogError(96, sb.ToString()); return false; } catch (Exception e) { //something else happened sb.AppendLine("Exception"); sb.AppendLine(e.Message); //logger.LogError(96, sb.ToString()); return false; //throw; } //... Si el token es invalido (=null) devuelve false return validatedToken != null; } public static string? DesCifrar(string value) { if (_encript.IsValid == false) return null; try { string? b64Decrypted = Base64Decode(value); if (String.IsNullOrEmpty(b64Decrypted)) return null; string decryptedText = ""; for (int i = 0; i < b64Decrypted!.Length; i++) { int encrypted = (int)b64Decrypted[i]; int decryption = encrypted - _encript.getSemilla(); decryptedText += Char.ConvertFromUtf32(decryption); } return decryptedText; } catch (Exception e) { //var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().AddEventLog()); //var logger = loggerFactory.CreateLogger("Decrypt"); var sb = new StringBuilder() .AppendLine("Error en: DesCifrar") .AppendLine("Exception") .AppendLine(e.Message); //logger.LogError(96, sb.ToString()); return null; } } public static string? Base64Decode(string base64EncodedData) { try { var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData); return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); } catch (Exception e) { var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().AddEventLog()); var logger = loggerFactory.CreateLogger("Base64Decode"); //var sb = new StringBuilder() // .AppendLine("Error en: Base64Decode") // .AppendLine("Exception") // .AppendLine(e.Message); //logger.LogError(96, sb.ToString()); return null; } } } }