diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 209694f..552bbf8 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -64,6 +64,7 @@ jobs: cd /opt/gestion-integral # Gitea reemplaza los secretos aquí. Es seguro. export DB_SA_PASSWORD='${{ secrets.DB_SA_PASSWORD_SECRET }}' + export JWT_KEY='${{ secrets.JWT_KEY_SECRET }}' docker compose up -d # --- PARTE 4: LIMPIEZA (EN EL HOST) --- diff --git a/Backend/GestionIntegral.Api/GestionIntegral.Api.csproj b/Backend/GestionIntegral.Api/GestionIntegral.Api.csproj index fe3b964..e262496 100644 --- a/Backend/GestionIntegral.Api/GestionIntegral.Api.csproj +++ b/Backend/GestionIntegral.Api/GestionIntegral.Api.csproj @@ -17,4 +17,12 @@ + + + + + PreserveNewest + + + diff --git a/Backend/GestionIntegral.Api/Program.cs b/Backend/GestionIntegral.Api/Program.cs index 2665c2d..de7dc45 100644 --- a/Backend/GestionIntegral.Api/Program.cs +++ b/Backend/GestionIntegral.Api/Program.cs @@ -93,15 +93,62 @@ builder.Services.AddScoped(); // Servicios de Reportes builder.Services.AddScoped(); + +// --- INICIO DE CAMBIOS: Configuración de Autenticación JWT --- + +// 1. Obtener la sección de configuración de JWT. +// Esto leerá desde appsettings.json y SOBRESCRIBIRÁ con variables de entorno si existen. +var jwtSection = builder.Configuration.GetSection("JwtSettings"); +var jwtKey = jwtSection["Key"]; +var jwtIssuer = jwtSection["Issuer"]; +var jwtAudience = jwtSection["Audience"]; + +// 2. Validar que todas las configuraciones necesarias existan. +if (string.IsNullOrEmpty(jwtKey) || string.IsNullOrEmpty(jwtIssuer) || string.IsNullOrEmpty(jwtAudience)) +{ + throw new InvalidOperationException("La configuración de JWT (Key, Issuer, Audience) no está completa. Verifique appsettings.json o las variables de entorno."); +} + +var keyBytes = Encoding.ASCII.GetBytes(jwtKey); + +builder.Services.AddAuthentication(options => +{ + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; +}) +.AddJwtBearer(options => +{ + // Es buena práctica usar HTTPS en producción. Si tu proxy inverso maneja SSL, esto puede ser false. + options.RequireHttpsMetadata = builder.Environment.IsProduction(); + options.SaveToken = true; + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(keyBytes), + + ValidateIssuer = true, + ValidIssuer = jwtIssuer, // Usar la variable leída de la configuración + + ValidateAudience = true, + ValidAudience = jwtAudience, // Usar la variable leída de la configuración + + ValidateLifetime = true, + ClockSkew = TimeSpan.Zero + }; +}); + + // --- Configuración de Autenticación JWT --- -var jwtSettings = builder.Configuration.GetSection("Jwt"); + +/*var jwtSettings = builder.Configuration.GetSection("Jwt"); // Le decimos que busque la clave JWT en la raíz de la configuración (donde están las variables de entorno). // Si no la encuentra, como respaldo, busca en la sección "Jwt" del appsettings. //var jwtKey = builder.Configuration["JWT_KEY"] ?? jwtSettings["Key"] ?? throw new ArgumentNullException("JWT_KEY or Jwt:Key not configured"); -var jwtKey = jwtSettings["Key"] ?? throw new ArgumentNullException("Jwt:Key", "JWT Key not configured in appsettings.json"); +//var jwtKey = jwtSettings["Key"] ?? throw new ArgumentNullException("Jwt:Key", "JWT Key not configured in appsettings.json"); -var keyBytes = Encoding.ASCII.GetBytes(jwtKey); +//var keyBytes = Encoding.ASCII.GetBytes(jwtKey); builder.Services.AddAuthentication(options => { @@ -124,7 +171,7 @@ builder.Services.AddAuthentication(options => ValidateLifetime = true, ClockSkew = TimeSpan.Zero }; -}); +});*/ // --- Configuración de Autorización --- builder.Services.AddAuthorization(); @@ -221,7 +268,7 @@ if (app.Environment.IsDevelopment()) app.UseCors(MyAllowSpecificOrigins); -app.UseAuthentication(); // Debe ir ANTES de UseAuthorization +app.UseAuthentication(); // SIEMPRE ANTES de UseAuthorization app.UseAuthorization(); app.MapControllers(); diff --git a/Backend/GestionIntegral.Api/appsettings.json b/Backend/GestionIntegral.Api/appsettings.json index 2e51861..3e37384 100644 --- a/Backend/GestionIntegral.Api/appsettings.json +++ b/Backend/GestionIntegral.Api/appsettings.json @@ -6,10 +6,10 @@ } }, "Jwt": { - "Key": "badb1a38d221c9e23bcf70958840ca7f5a5dc54f2047dadf7ce45b578b5bc3e2", - "Issuer": "GestionIntegralApi", - "Audience": "GestionIntegralClient", + "Key": "", + "Issuer": "", + "Audience": "", "DurationInHours": 8 }, "AllowedHosts": "*" -} +} \ No newline at end of file