feat: Añadidos de seguridad (Backend, Frontend e IA)
Implementación de medidas de seguridad críticas tras auditoría: Backend (API & IA): - Anti-Prompt Injection: Reestructuración de prompts con delimitadores XML y sanitización estricta de inputs (Tag Injection). - Anti-SSRF: Implementación de servicio `UrlSecurity` para validar URLs y bloquear accesos a IPs internas/privadas en funciones de scraping. - Moderación: Activación de `SafetySettings` en Gemini API. - Infraestructura: - Configuración de Headers de seguridad (HSTS, CSP, NoSniff). - CORS restrictivo (solo métodos HTTP necesarios). - Rate Limiting global y política estricta para Login (5 req/min). - Timeouts en HttpClient para prevenir DoS. - Auth: Endpoint `setup-admin` restringido exclusivamente a entorno Debug. Frontend (React): - Anti-XSS & Tabnabbing: Configuración de esquema estricto en `rehype-sanitize` y forzado de `rel="noopener noreferrer"` en enlaces. - Validación de longitud de input en cliente. IA: - Se realiza afinación de contexto de preguntas.
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
// /Controllers/AuthController.cs
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
@@ -6,6 +5,7 @@ using System.ComponentModel.DataAnnotations;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
|
||||
public class LoginRequest
|
||||
{
|
||||
@@ -26,7 +26,6 @@ public class AuthController : ControllerBase
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly UserManager<IdentityUser> _userManager;
|
||||
|
||||
// Inyectamos el UserManager que gestiona los usuarios
|
||||
public AuthController(IConfiguration configuration, UserManager<IdentityUser> userManager)
|
||||
{
|
||||
_configuration = configuration;
|
||||
@@ -34,12 +33,11 @@ public class AuthController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost("login")]
|
||||
[EnableRateLimiting("login-limit")]
|
||||
public async Task<IActionResult> Login([FromBody] LoginRequest loginRequest)
|
||||
{
|
||||
// Buscamos al usuario por su nombre
|
||||
var user = await _userManager.FindByNameAsync(loginRequest.Username);
|
||||
|
||||
// Verificamos si el usuario existe y si la contraseña es correcta
|
||||
if (user != null && await _userManager.CheckPasswordAsync(user, loginRequest.Password))
|
||||
{
|
||||
var token = GenerateJwtToken(user);
|
||||
@@ -49,7 +47,8 @@ public class AuthController : ControllerBase
|
||||
return Unauthorized("Credenciales inválidas.");
|
||||
}
|
||||
|
||||
// Método para crear el primer usuario administrador (solo para configuración inicial)
|
||||
#if DEBUG
|
||||
// [SEGURIDAD] Endpoint solo para desarrollo
|
||||
[HttpPost("setup-admin")]
|
||||
public async Task<IActionResult> SetupAdminUser()
|
||||
{
|
||||
@@ -61,6 +60,7 @@ public class AuthController : ControllerBase
|
||||
UserName = "admin",
|
||||
Email = "tecnica@eldia.com",
|
||||
};
|
||||
// En producción usar Secrets, no hardcoded
|
||||
var result = await _userManager.CreateAsync(adminUser, "Diagonal423");
|
||||
|
||||
if (result.Succeeded)
|
||||
@@ -71,6 +71,7 @@ public class AuthController : ControllerBase
|
||||
}
|
||||
return Ok("El usuario administrador ya existe.");
|
||||
}
|
||||
#endif
|
||||
|
||||
private string GenerateJwtToken(IdentityUser user)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user