using Microsoft.Extensions.Options;
namespace LittleShop.Services;
///
/// Validates critical configuration settings on startup to prevent security issues
///
public class ConfigurationValidationService
{
private readonly IConfiguration _configuration;
private readonly IWebHostEnvironment _environment;
private readonly ILogger _logger;
public ConfigurationValidationService(
IConfiguration configuration,
IWebHostEnvironment environment,
ILogger logger)
{
_configuration = configuration;
_environment = environment;
_logger = logger;
}
///
/// Validates all critical configuration settings on startup
/// Throws exceptions for security-critical misconfigurations
///
public void ValidateConfiguration()
{
_logger.LogInformation("🔍 Validating application configuration...");
// JWT validation is critical in production, optional in development/testing
if (_environment.IsProduction() || !string.IsNullOrEmpty(_configuration["Jwt:Key"]))
{
ValidateJwtConfiguration();
}
else if (_environment.IsDevelopment())
{
_logger.LogWarning("⚠️ JWT validation skipped in development. Configure Jwt:Key for production readiness.");
}
ValidateSilverPayConfiguration();
ValidateProductionSafeguards();
ValidateEnvironmentConfiguration();
_logger.LogInformation("✅ Configuration validation completed successfully");
}
private void ValidateJwtConfiguration()
{
var jwtKey = _configuration["Jwt:Key"];
if (string.IsNullOrEmpty(jwtKey))
{
throw new InvalidOperationException("🚨 CRITICAL: JWT Key not configured. Set Jwt:Key in appsettings.json");
}
// Check for the old hardcoded key
if (jwtKey.Contains("ThisIsASuperSecretKey"))
{
throw new InvalidOperationException("🚨 CRITICAL: Default JWT key detected. Generate a new secure key!");
}
// Require minimum key length for security
if (jwtKey.Length < 32)
{
throw new InvalidOperationException("🚨 CRITICAL: JWT key too short. Must be at least 32 characters.");
}
_logger.LogInformation("✅ JWT configuration validated");
}
private void ValidateSilverPayConfiguration()
{
var baseUrl = _configuration["SilverPay:BaseUrl"];
var apiKey = _configuration["SilverPay:ApiKey"];
if (string.IsNullOrEmpty(baseUrl))
{
throw new InvalidOperationException("🚨 CRITICAL: SilverPay BaseUrl not configured");
}
if (string.IsNullOrEmpty(apiKey))
{
throw new InvalidOperationException("🚨 CRITICAL: SilverPay ApiKey not configured");
}
// Check for test/mock indicators in production
if (_environment.IsProduction())
{
if (baseUrl.Contains("localhost") || baseUrl.Contains("127.0.0.1"))
{
throw new InvalidOperationException("🚨 CRITICAL: SilverPay configured with localhost in production!");
}
if (apiKey.Contains("test") || apiKey.Contains("mock") || apiKey.Contains("demo"))
{
_logger.LogWarning("⚠️ WARNING: SilverPay API key contains test/mock indicators in production");
}
}
_logger.LogInformation("✅ SilverPay configuration validated");
}
private void ValidateProductionSafeguards()
{
// Ensure no mock services can be accidentally enabled
var mockServiceConfig = _configuration.GetSection("SilverPay").GetChildren()
.Where(x => x.Key.ToLower().Contains("mock") || x.Key.ToLower().Contains("test"))
.ToList();
if (mockServiceConfig.Any())
{
foreach (var config in mockServiceConfig)
{
_logger.LogWarning("⚠️ Found mock/test configuration: {Key} = {Value}", config.Key, config.Value);
}
}
// In production, absolutely no mock configurations should exist
if (_environment.IsProduction())
{
var useMockService = _configuration.GetValue("SilverPay:UseMockService", false);
if (useMockService)
{
throw new InvalidOperationException("🚨 CRITICAL: Mock service enabled in production! Set SilverPay:UseMockService to false");
}
// Check for any configuration that might enable testing/mocking
var dangerousConfigs = new[]
{
"Testing:Enabled",
"Mock:Enabled",
"Development:MockPayments",
"Debug:MockServices"
};
foreach (var configKey in dangerousConfigs)
{
if (_configuration.GetValue(configKey, false))
{
throw new InvalidOperationException($"🚨 CRITICAL: Dangerous test configuration enabled in production: {configKey}");
}
}
}
_logger.LogInformation("✅ Production safeguards validated");
}
private void ValidateEnvironmentConfiguration()
{
// Log current environment for verification
_logger.LogInformation("🌍 Environment: {Environment}", _environment.EnvironmentName);
// Validate database connection
var connectionString = _configuration.GetConnectionString("DefaultConnection");
if (string.IsNullOrEmpty(connectionString))
{
throw new InvalidOperationException("🚨 CRITICAL: Database connection string not configured");
}
// Check for development database in production
if (_environment.IsProduction() && connectionString.Contains("littleshop.db"))
{
_logger.LogWarning("⚠️ WARNING: Using SQLite database in production. Consider PostgreSQL/SQL Server for production.");
}
_logger.LogInformation("✅ Environment configuration validated");
}
}