using Microsoft.Extensions.Configuration; namespace WebApp.Authentication; public class AuthenticationService { private readonly IConfiguration _configuration; private readonly ILogger _logger; public AuthenticationService(IConfiguration configuration, ILogger logger) { _configuration = configuration; _logger = logger; } public AuthenticationResult ValidateCredentials(string email, string password) { try { // Bind User Secrets to AuthenticationSettings var authSettings = new AuthenticationSettings(); _configuration.GetSection("Authentication").Bind(authSettings); if (authSettings.Users == null || !authSettings.Users.Any()) { _logger.LogWarning("No users configured in authentication settings"); return AuthenticationResult.Failed("Authentication system not configured"); } // Find user by email (case-insensitive) var user = authSettings.Users .FirstOrDefault(u => u.Email.Equals(email, StringComparison.OrdinalIgnoreCase)); if (user == null) { _logger.LogDebug("User not found: {Email}", email); return AuthenticationResult.Failed("Invalid email or password"); } // Verify password using BCrypt if (!BCrypt.Net.BCrypt.Verify(password, user.PasswordHash)) { _logger.LogDebug("Invalid password for user: {Email}", email); return AuthenticationResult.Failed("Invalid email or password"); } // Success _logger.LogDebug("Successful credential validation for {Email}", email); return AuthenticationResult.Success(user.Email, user.DisplayName, user.Role); } catch (Exception ex) { _logger.LogError(ex, "Error during credential validation"); return AuthenticationResult.Failed("An error occurred during authentication"); } } } public class AuthenticationResult { public bool IsSuccess { get; set; } public string? Email { get; set; } public string? DisplayName { get; set; } public string? Role { get; set; } public string? ErrorMessage { get; set; } public static AuthenticationResult Success(string email, string displayName, string role) => new() { IsSuccess = true, Email = email, DisplayName = displayName, Role = role }; public static AuthenticationResult Failed(string error) => new() { IsSuccess = false, ErrorMessage = error }; }