Skip to main content

Authentication Password

A secure password-based authentication module that integrates with the MasLazu.AspNet.Authentication.Core framework. This module provides password authentication functionality with BCrypt hashing, user registration, and login capabilities.

๐ŸŽฏ Purposeโ€‹

The Authentication.Password module extends the core authentication system with password-based login functionality:

  • User Registration - Account creation with password-based authentication
  • Password Login - Secure authentication using BCrypt hashing
  • Password Management - Change password functionality
  • Email Verification - Optional email verification integration
  • Clean Architecture - Follows framework patterns with clear separation of concerns

๐Ÿ“ฆ Package Structureโ€‹

๐Ÿ—๏ธ Architecture Overviewโ€‹

This module integrates with the existing Authentication.Core framework:

๐Ÿš€ Installationโ€‹

# Core password authentication
dotnet add package MasLazu.AspNet.Authentication.Password

# Database layer
dotnet add package MasLazu.AspNet.Authentication.Password.EfCore

# API endpoints
dotnet add package MasLazu.AspNet.Authentication.Password.Endpoint

# Abstractions (for DI)
dotnet add package MasLazu.AspNet.Authentication.Password.Abstraction

โš™๏ธ Configurationโ€‹

1. Service Registrationโ€‹

// Program.cs
var builder = WebApplication.CreateBuilder(args);

// Add Authentication.Core (required dependency)
builder.Services.AddAuthenticationCoreApplication(builder.Configuration);

// Add Password Authentication
builder.Services.AddAuthenticationPasswordApplication(builder.Configuration);

// Add EF Core for Password entities
builder.Services.AddAuthenticationPasswordEntityFrameworkCore();

// Add endpoints
builder.Services.AddFastEndpoints();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();
app.UseFastEndpoints();

app.Run();

2. Configuration Settingsโ€‹

{
"PasswordLoginMethod": {
"RequireVerification": true,
"PasswordValidation": {
"MinLength": 8,
"RequireUppercase": true,
"RequireLowercase": true,
"RequireDigit": true,
"RequireSpecialCharacter": false
}
}
}

๐Ÿ” Core Featuresโ€‹

1. User Registrationโ€‹

public record PasswordRegisterRequest(
string Name,
string Username,
string Email,
string Password
);

// API: POST /auth/register
var request = new PasswordRegisterRequest(
Name: "John Doe",
Username: "johndoe",
Email: "john.doe@example.com",
Password: "SecurePass123!"
);

2. User Loginโ€‹

public record PasswordLoginRequest(
string Identifier, // Email or Username
string Password
);

// API: POST /auth/login
var loginRequest = new PasswordLoginRequest(
Identifier: "john.doe@example.com", // or "johndoe"
Password: "SecurePass123!"
);

3. Password Changeโ€‹

public record ChangePasswordRequest(
string CurrentPassword,
string NewPassword
);

// API: POST /auth/change-password (requires authentication)
var changeRequest = new ChangePasswordRequest(
CurrentPassword: "OldPass123!",
NewPassword: "NewSecurePass456!"
);

๐Ÿ›ก๏ธ Security Implementationโ€‹

1. BCrypt Password Hashingโ€‹

public static class PasswordHasher
{
private const int WorkFactor = 12; // 2^12 = 4096 iterations

public static string HashPassword(string password)
{
return BCrypt.Net.BCrypt.HashPassword(password, WorkFactor);
}

public static bool VerifyPassword(string hashedPassword, string providedPassword)
{
return BCrypt.Net.BCrypt.Verify(providedPassword, hashedPassword);
}
}

2. Password Validation Configurationโ€‹

public class PasswordValidationConfiguration
{
public int MinLength { get; set; } = 8;
public bool RequireUppercase { get; set; } = true;
public bool RequireLowercase { get; set; } = true;
public bool RequireDigit { get; set; } = true;
public bool RequireSpecialCharacter { get; set; } = false;
}

๐Ÿ“Š Database Schemaโ€‹

UserPasswordLogin Entityโ€‹

public class UserPasswordLogin : BaseEntity
{
public Guid UserId { get; set; }
public Guid UserLoginMethodId { get; set; }
public bool IsVerified { get; set; }
public string PasswordHash { get; set; } = string.Empty;
public DateTime? LastLoginDate { get; set; }
}

Entity Configurationโ€‹

public class UserPasswordLoginConfiguration : IEntityTypeConfiguration<UserPasswordLogin>
{
public void Configure(EntityTypeBuilder<UserPasswordLogin> builder)
{
builder.HasKey(upl => upl.Id);

builder.Property(upl => upl.UserLoginMethodId)
.IsRequired();

builder.Property(upl => upl.PasswordHash)
.IsRequired()
.HasMaxLength(500);

builder.HasIndex(upl => upl.UserLoginMethodId)
.IsUnique();
}
}

๐Ÿ”— API Endpointsโ€‹

All endpoints are grouped under /auth prefix:

MethodEndpointDescriptionRequestAuthentication
POST/auth/registerRegister new userPasswordRegisterRequestNone
POST/auth/loginUser loginPasswordLoginRequestNone
POST/auth/change-passwordChange passwordChangePasswordRequestRequired

Registration Flowโ€‹

// 1. Register user
var registerResponse = await httpClient.PostAsJsonAsync("/auth/register", new PasswordRegisterRequest(
Name: "John Doe",
Username: "johndoe",
Email: "john@example.com",
Password: "SecurePass123!"
));

// 2. Email verification sent automatically (if configured)
// 3. User can login after verification (if required)

Login Flowโ€‹

// Login with email or username
var loginResponse = await httpClient.PostAsJsonAsync("/auth/login", new PasswordLoginRequest(
Identifier: "john@example.com", // or "johndoe"
Password: "SecurePass123!"
));

var loginResult = await loginResponse.Content.ReadFromJsonAsync<PasswordLoginResponse>();
// Returns JWT tokens from Authentication.Core

๐Ÿ”ง Service Implementationโ€‹

Core Service Interfaceโ€‹

public interface IUserPasswordLoginService : ICrudService<UserPasswordLoginDto, CreateUserPasswordLoginRequest, UpdateUserPasswordLoginRequest>
{
Task<PasswordLoginResponse> LoginAsync(PasswordLoginRequest request, CancellationToken ct);
Task RegisterAsync(PasswordRegisterRequest request, CancellationToken ct);
Task ChangePasswordAsync(Guid userId, ChangePasswordRequest request, CancellationToken ct);
}

Registration Processโ€‹

The service integrates with multiple systems:

  1. User Creation - Uses IUserService from Authentication.Core
  2. Login Method - Creates entry in IUserLoginMethodService
  3. Password Storage - Stores BCrypt hash in UserPasswordLogin
  4. Email Verification - Triggers verification email if enabled

Login Validationโ€‹

public async Task<PasswordLoginResponse> LoginAsync(PasswordLoginRequest request, CancellationToken ct)
{
// 1. Find user by email or username
UserDto user = await _userService.GetByUsernameOrEmailAsync(request.Identifier, ct);

// 2. Get password login record
UserPasswordLogin? userPasswordLogin = await ReadRepository.FirstOrDefaultAsync(upl => upl.UserId == user.Id, ct);

// 3. Verify password with BCrypt
if (!PasswordHasher.VerifyPassword(userPasswordLogin.PasswordHash, request.Password))
throw new UnauthorizedException("Invalid username/email or password.");

// 4. Check verification status
if (_passwordConfig.RequireVerification && !userPasswordLogin.IsVerified)
throw new UnauthorizedException("Account not verified.");

// 5. Generate JWT tokens via Authentication.Core
return (await _authService.LoginAsync(userPasswordLogin.UserLoginMethodId, ct)).Adapt<PasswordLoginResponse>();
}

๐Ÿงช Testing Examplesโ€‹

Integration Test Setupโ€‹

public class PasswordAuthenticationTests : IClassFixture<WebApplicationFactory<Program>>
{
private readonly HttpClient _client;

public PasswordAuthenticationTests(WebApplicationFactory<Program> factory)
{
_client = factory.CreateClient();
}

[Fact]
public async Task Register_ValidRequest_ReturnsSuccess()
{
var request = new PasswordRegisterRequest(
Name: "Test User",
Username: "testuser",
Email: "test@example.com",
Password: "TestPass123!"
);

var response = await _client.PostAsJsonAsync("/auth/register", request);

response.StatusCode.Should().Be(HttpStatusCode.OK);
}

[Fact]
public async Task Login_ValidCredentials_ReturnsTokens()
{
// Arrange: First register a user
await RegisterTestUser();

// Act: Login
var loginRequest = new PasswordLoginRequest("test@example.com", "TestPass123!");
var response = await _client.PostAsJsonAsync("/auth/login", loginRequest);

// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
var loginResponse = await response.Content.ReadFromJsonAsync<PasswordLoginResponse>();
loginResponse.AccessToken.Should().NotBeNullOrEmpty();
}
}

๐Ÿ“ Project Structureโ€‹

Based on actual implementation:

MasLazu.AspNet.Authentication.Password/
โ”œโ”€โ”€ src/
โ”‚ โ”œโ”€โ”€ MasLazu.AspNet.Authentication.Password.Abstraction/
โ”‚ โ”‚ โ”œโ”€โ”€ Interfaces/
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ IUserPasswordLoginService.cs
โ”‚ โ”‚ โ””โ”€โ”€ Models/
โ”‚ โ”‚ โ”œโ”€โ”€ PasswordRegisterRequest.cs
โ”‚ โ”‚ โ”œโ”€โ”€ PasswordLoginRequest.cs
โ”‚ โ”‚ โ”œโ”€โ”€ ChangePasswordRequest.cs
โ”‚ โ”‚ โ””โ”€โ”€ UserPasswordLoginDto.cs
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ MasLazu.AspNet.Authentication.Password.Domain/
โ”‚ โ”‚ โ””โ”€โ”€ Entities/
โ”‚ โ”‚ โ””โ”€โ”€ UserPasswordLogin.cs
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ MasLazu.AspNet.Authentication.Password/
โ”‚ โ”‚ โ”œโ”€โ”€ Services/
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ UserPasswordLoginService.cs
โ”‚ โ”‚ โ”œโ”€โ”€ Utils/
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ PasswordHasher.cs
โ”‚ โ”‚ โ”œโ”€โ”€ Configurations/
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ PasswordLoginMethodConfiguration.cs
โ”‚ โ”‚ โ””โ”€โ”€ Extensions/
โ”‚ โ”‚ โ””โ”€โ”€ AuthenticationPasswordApplicationExtension.cs
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ MasLazu.AspNet.Authentication.Password.EfCore/
โ”‚ โ”‚ โ”œโ”€โ”€ Configurations/
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ UserPasswordLoginConfiguration.cs
โ”‚ โ”‚ โ””โ”€โ”€ Extensions/
โ”‚ โ”‚ โ””โ”€โ”€ ServiceCollectionExtensions.cs
โ”‚ โ”‚
โ”‚ โ””โ”€โ”€ MasLazu.AspNet.Authentication.Password.Endpoint/
โ”‚ โ”œโ”€โ”€ Endpoints/
โ”‚ โ”‚ โ”œโ”€โ”€ RegisterEndpoint.cs
โ”‚ โ”‚ โ”œโ”€โ”€ LoginEndpoint.cs
โ”‚ โ”‚ โ””โ”€โ”€ ChangePasswordEndpoint.cs
โ”‚ โ””โ”€โ”€ EndpointGroups/
โ”‚ โ””โ”€โ”€ AuthEndpointGroup.cs
โ”‚
โ””โ”€โ”€ MasLazu.AspNet.Authentication.Password.sln

๐Ÿ”— Dependenciesโ€‹

Required Framework Componentsโ€‹

  • MasLazu.AspNet.Authentication.Core.Abstraction - Core authentication services
  • MasLazu.AspNet.Framework.Application - Base application layer
  • MasLazu.AspNet.Verification.Abstraction - Email verification (optional)

External Packagesโ€‹

  • BCrypt.Net-Next - Password hashing
  • FastEndpoints - API endpoints
  • Entity Framework Core - Data access

โœ… Best Practicesโ€‹

โœ… Security Do'sโ€‹

  • Use BCrypt with work factor 12 for password hashing
  • Integrate with verification for email confirmation
  • Leverage Authentication.Core for JWT token management
  • Validate all inputs with FluentValidation
  • Use records for immutable request/response models

โŒ Security Don'tsโ€‹

  • Don't store plain passwords - always use BCrypt hash
  • Don't skip verification when security is critical
  • Don't bypass the core auth system - use provided services
  • Don't log sensitive data - exclude passwords from logs

๐ŸŽฏ Integration Pointsโ€‹

With Authentication.Coreโ€‹

// Password module uses core services for:
// - User management (IUserService)
// - JWT tokens (IAuthService)
// - Login methods (IUserLoginMethodService)

With Verification Moduleโ€‹

// Email verification integration:
await _userService.SendEmailVerificationAsync(userDto.Email!, ct);

With Frameworkโ€‹

// Extends framework base classes:
// - CrudService for standard operations
// - BaseEntity for domain entities
// - BaseEndpoint for API endpoints

๐ŸŽฏ Next Stepsโ€‹

  1. Authentication.Core - Core JWT authentication and user management
  2. Verification Module - Email verification integration
  3. Framework Overview - Understanding the base framework