281 lines
11 KiB
C#
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;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|