Apigateway/ApiGateway/CustomLogic.cs

281 lines
11 KiB
C#
Raw Permalink Normal View History

2023-09-01 09:19:18 -05:00
using Microsoft.Extensions.FileSystemGlobbing.Internal;
using Microsoft.IdentityModel.Tokens;
2022-11-02 11:31:23 -05:00
using Ocelot.Configuration;
using Ocelot.Middleware;
using Security;
using System.IdentityModel.Tokens.Jwt;
2023-01-10 10:35:15 -05:00
using System.IO;
2022-11-02 11:31:23 -05:00
using System.Security.Claims;
2023-01-10 10:35:15 -05:00
using System.Security.Policy;
2022-11-02 11:31:23 -05:00
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
2022-11-02 11:31:23 -05:00
2024-02-09 17:57:46 -05:00
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().AddEventLog());
var logger = loggerFactory.CreateLogger("Auth");
2023-01-10 10:35:15 -05:00
2023-02-14 18:01:33 -05:00
//TODO: ELIMINAR ESTAS RUTAS POR COMPLETO!
// TknCambioClave
// Desencriptar - encriptar
string calledUrl = ctx.Items.DownstreamRoute().UpstreamPathTemplate.OriginalValue;
2022-11-02 11:31:23 -05:00
2024-01-25 16:58:57 -05:00
//logger.LogError(71, $"DownstreamRoute: {calledUrl}");
2022-11-02 11:31:23 -05:00
// Excepcion para login, no requiere token
if (
String.Equals(calledUrl, "/ldap/Conectar") ||
String.Equals(calledUrl, "/Ext/Login") ||
String.Equals(calledUrl, "/Auth/Login") ||
2024-08-26 11:01:08 -05:00
String.Equals(calledUrl, "/Auth/BloquearUsuario") ||
2023-02-14 18:01:33 -05:00
String.Equals(calledUrl, "/Auth/CambiarClave") ||
2024-08-26 11:01:08 -05:00
String.Equals(calledUrl, "/UsuariosTemp") ||
2023-02-14 18:01:33 -05:00
String.Equals(calledUrl, "/Auth/TknCambioClave") ||
String.Equals(calledUrl, "/Auth/Proveedor") ||
2024-09-23 08:54:57 -05:00
String.Equals(calledUrl, "/Auth/RecuperarClave") ||
2023-09-01 09:19:18 -05:00
String.Equals(calledUrl, "/Email") ||
String.Equals(calledUrl, "/Formularios/Graficas/{rutaGrafica}")
)
2023-09-01 09:19:18 -05:00
{
2022-11-02 11:31:23 -05:00
return true;
2023-09-01 09:19:18 -05:00
}
// 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;
//}
2022-11-02 11:31:23 -05:00
try
{
2023-01-10 10:35:15 -05:00
//string path = ctx.Request.Path;
2022-11-02 11:31:23 -05:00
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.");
2022-11-02 11:31:23 -05:00
//
2022-11-02 11:31:23 -05:00
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");
2022-11-02 11:31:23 -05:00
//Token invalido (firma invalida)
2022-11-02 11:31:23 -05:00
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");
2022-11-02 11:31:23 -05:00
//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;
2022-11-02 11:31:23 -05:00
//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
{
2024-11-16 09:35:32 -05:00
if (cl.Type == claim.Key && String.Equals(claim.Key, "prm"))
2022-11-02 11:31:23 -05:00
{
2024-11-16 09:48:01 -05:00
string separador = "::";
2022-11-02 11:31:23 -05:00
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.");
2022-11-02 11:31:23 -05:00
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)
{
2024-02-09 17:57:46 -05:00
logger.LogError(71, e.Message);
2022-11-02 11:31:23 -05:00
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");
2023-01-10 10:35:15 -05:00
var sb = new StringBuilder()
.AppendLine("Error en: VerifyToken");
2022-11-02 11:31:23 -05:00
var validationParameters = new TokenValidationParameters()
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Encripter.HashKey!))
2022-11-02 11:31:23 -05:00
};
var tokenHandler = new JwtSecurityTokenHandler();
SecurityToken? validatedToken = null;
2022-11-02 11:31:23 -05:00
try
{
tokenHandler.ValidateToken(token, validationParameters, out validatedToken);
}
2023-01-10 10:35:15 -05:00
catch (SecurityTokenException se)
2022-11-02 11:31:23 -05:00
{
2023-01-10 10:35:15 -05:00
sb.AppendLine("SecurityTokenException");
sb.AppendLine(se.Message);
//logger.LogError(96, sb.ToString());
2022-11-02 11:31:23 -05:00
return false;
}
catch (Exception e)
{
2023-01-10 10:35:15 -05:00
2022-11-02 11:31:23 -05:00
//something else happened
2023-01-10 10:35:15 -05:00
sb.AppendLine("Exception");
sb.AppendLine(e.Message);
//logger.LogError(96, sb.ToString());
2022-11-02 11:31:23 -05:00
return false;
//throw;
}
//... Si el token es invalido (=null) devuelve false
2022-11-02 11:31:23 -05:00
return validatedToken != null;
}
public static string? DesCifrar(string value)
2023-01-10 10:35:15 -05:00
{
2022-11-02 11:31:23 -05:00
if (_encript.IsValid == false) return null;
try
{
string? b64Decrypted = Base64Decode(value);
if (String.IsNullOrEmpty(b64Decrypted)) return null;
2022-11-02 11:31:23 -05:00
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;
}
2023-01-10 10:35:15 -05:00
catch (Exception e)
2022-11-02 11:31:23 -05:00
{
//var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().AddEventLog());
//var logger = loggerFactory.CreateLogger("Decrypt");
2023-01-10 10:35:15 -05:00
var sb = new StringBuilder()
.AppendLine("Error en: DesCifrar")
.AppendLine("Exception")
.AppendLine(e.Message);
//logger.LogError(96, sb.ToString());
2022-11-02 11:31:23 -05:00
return null;
}
}
public static string? Base64Decode(string base64EncodedData)
{
try
{
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
2023-01-10 10:35:15 -05:00
catch (Exception e)
2022-11-02 11:31:23 -05:00
{
2023-01-10 10:35:15 -05:00
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());
2022-11-02 11:31:23 -05:00
return null;
}
}
}
}