diff --git a/docker-compose.yml b/docker-compose.yml index 9dc4421..433fe89 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -44,7 +44,10 @@ services: ASPNETCORE_URLS: http://0.0.0.0:5005 Database__Provider: postgres ConnectionStrings__Default: "Host=db;Port=5432;Database=hokm;Username=hokm;Password=${POSTGRES_PASSWORD:-hokm_dev_pass}" - Jwt__Key: ${JWT_KEY:?set JWT_KEY in .env} + # Default empty so `docker compose build` (which interpolates the whole file) + # never blocks on a runtime-only secret. The server REFUSES to boot in + # Production with a missing/dev key (see Program.cs guard). + Jwt__Key: ${JWT_KEY:-} Jwt__Issuer: ${JWT_ISSUER:-hokm} Jwt__Audience: ${JWT_AUDIENCE:-hokm-clients} # Comma-separated origins the browser uses to reach the web app. diff --git a/server/src/Hokm.Server/Program.cs b/server/src/Hokm.Server/Program.cs index 5608039..5d97393 100644 --- a/server/src/Hokm.Server/Program.cs +++ b/server/src/Hokm.Server/Program.cs @@ -15,9 +15,14 @@ using Microsoft.IdentityModel.Tokens; var builder = WebApplication.CreateBuilder(args); // --- options --- +const string DevJwtKey = "dev-only-insecure-key-change-me-please-32+bytes!!"; var jwt = builder.Configuration.GetSection("Jwt").Get() ?? new JwtOptions(); if (string.IsNullOrWhiteSpace(jwt.Key)) - jwt.Key = "dev-only-insecure-key-change-me-please-32+bytes!!"; + jwt.Key = DevJwtKey; +// In Production a real secret is mandatory — refuse to boot with the dev key. +if (builder.Environment.IsProduction() && (jwt.Key == DevJwtKey || jwt.Key.Length < 32)) + throw new InvalidOperationException( + "Jwt:Key (env JWT_KEY) must be a 32+ char secret in Production. Set it in ENV_FILE: openssl rand -hex 32"); builder.Services.AddSingleton(jwt); builder.Services.AddSingleton(); builder.Services.AddSingleton();