Apigateway/ApiGateway/CustomLogic.cs
Cristian Guerrero 8e6425fc54 Prueba remoto
2024-11-16 09:48:01 -05:00

281 lines
11 KiB
C#

using Microsoft.Extensions.FileSystemGlobbing.Internal;
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;
//logger.LogError(71, $"DownstreamRoute: {calledUrl}");
// Excepcion para login, no requiere token
if (
String.Equals(calledUrl, "/ldap/Conectar") ||
String.Equals(calledUrl, "/Ext/Login") ||
String.Equals(calledUrl, "/Auth/Login") ||
String.Equals(calledUrl, "/Auth/BloquearUsuario") ||
String.Equals(calledUrl, "/Auth/CambiarClave") ||
String.Equals(calledUrl, "/UsuariosTemp") ||
String.Equals(calledUrl, "/Auth/TknCambioClave") ||
String.Equals(calledUrl, "/Auth/Proveedor") ||
String.Equals(calledUrl, "/Auth/RecuperarClave") ||
String.Equals(calledUrl, "/Email") ||
String.Equals(calledUrl, "/Formularios/Graficas/{rutaGrafica}")
)
{
return true;
}
// Define the regular expression pattern
//string patternGraficosHc = @"^\/Formularios\/Graficas\/[A-Za-z0-9]+\.[A-Za-z]+$";
//Regex regex = new Regex(patternGraficosHc);
//bool isMatch = regex.IsMatch(calledUrl);
//logger.LogError(71, $"isMatch: {isMatch}");
//if (isMatch)
//{
// 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<Claim>();
//where are stored the required claims for the route
Dictionary<string, string> required = route.RouteClaimsRequirement;
Regex reor = new Regex(@"[^,\s+$ ][^\,]*[^,\s+$ ]");
MatchCollection matches;
Regex reand = new Regex(@"[^&\s+$ ][^\&]*[^&\s+$ ]");
MatchCollection matchesand;
//int cont = 0;
foreach (KeyValuePair<string, string> 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, "prm"))
{
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;
}
}
}
}