Authentication Core
A comprehensive authentication and user management module built on MasLazu.AspNet Framework, providing JWT-based authentication, user profile management, and multi-language support with clean architecture principles.
🎯 Purpose
The Authentication.Core module provides a complete authentication system:
- JWT Authentication with access and refresh tokens
- User Management with comprehensive profiles
- Multi-Login Methods support (email, phone, etc.)
- Email/Phone Verification workflows
- Reference Data Management (languages, timezones, genders)
- High-Performance APIs using FastEndpoints
📦 Installation
# Core abstractions and interfaces
dotnet add package MasLazu.AspNet.Authentication.Core.Abstraction
# Business logic implementations
dotnet add package MasLazu.AspNet.Authentication.Core.Base
# Domain entities
dotnet add package MasLazu.AspNet.Authentication.Core.Domain
# API endpoints
dotnet add package MasLazu.AspNet.Authentication.Core.Endpoint
# Database implementation
dotnet add package MasLazu.AspNet.Authentication.Core.EfCore
🏗️ Architecture Overview
🚀 Core Features
1. JWT Authentication System
public class AuthService : IAuthService
{
public async Task<LoginResponse> LoginAsync(Guid userLoginMethodId, CancellationToken ct = default)
{
// Validate user and login method
var userLoginMethod = await _userLoginMethodRepository.GetByIdAsync(userLoginMethodId, ct);
var user = await _userRepository.GetByIdAsync(userLoginMethod.UserId, ct);
// Generate tokens
var (accessToken, accessTokenExpiresAt) = _jwtUtil.GenerateAccessToken(user.Id, user.Email);
var (refreshToken, refreshTokenExpiresAt) = _jwtUtil.GenerateRefreshToken(user.Id);
return new LoginResponse(
accessToken,
refreshToken,
accessTokenExpiresAt,
refreshTokenExpiresAt
);
}
}
2. User Management
public class UserService : CrudService<User, UserDto, CreateUserRequest, UpdateUserRequest>
{
public async Task<UserDto> CreateUserWithVerificationAsync(
CreateUserRequest request,
CancellationToken ct = default)
{
// Create user
var user = await CreateAsync(Guid.Empty, request, ct);
// Send verification email
if (!string.IsNullOrEmpty(request.Email))
{
await _verificationService.SendEmailVerificationAsync(user.Id, request.Email, ct);
}
return user;
}
public async Task<UserDto> VerifyEmailAsync(Guid userId, string code, CancellationToken ct = default)
{
// Verify the code
var isValid = await _verificationService.VerifyEmailAsync(userId, code, ct);
if (!isValid)
throw new ValidationException("Invalid verification code");
// Update user
var user = await Repository.GetByIdAsync(userId, ct);
user.IsEmailVerified = true;
user.UpdatedAt = DateTime.UtcNow;
await Repository.UpdateAsync(user, ct);
await UnitOfWork.SaveChangesAsync(ct);
return user.Adapt<UserDto>();
}
}
3. Multi-Language & Timezone Support
public class User : BaseEntity
{
public string Name { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string? PhoneNumber { get; set; }
public string? Username { get; set; }
// Localization
public string LanguageCode { get; set; } = "en";
public Guid? TimezoneId { get; set; }
public string? GenderCode { get; set; }
// Verification status
public bool IsEmailVerified { get; set; }
public bool IsPhoneNumberVerified { get; set; }
// Navigation properties
public Timezone? Timezone { get; set; }
public Gender? Gender { get; set; }
public Language? Language { get; set; }
public ICollection<UserLoginMethod> UserLoginMethods { get; set; } = new List<UserLoginMethod>();
}
🔧 Configuration & Setup
1. JWT Configuration
{
"Jwt": {
"Key": "your-super-secret-jwt-signing-key-256-bits-minimum",
"Secret": "your-super-secret-jwt-signing-key-256-bits-minimum",
"Issuer": "https://yourapp.com",
"Audience": "https://yourapp.com",
"AccessTokenExpirationMinutes": 120,
"RefreshTokenExpirationDays": 30
}
}
2. Service Registration
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// JWT Configuration
builder.Services.Configure<JwtConfiguration>(
builder.Configuration.GetSection("Jwt"));
// Authentication Core Services
builder.Services.AddAuthenticationCoreApplicationServices();
// Database
builder.Services.AddDbContext<AuthenticationDbContext>(options =>
options.UseNpgsql(connectionString));
// Framework services
builder.Services.AddFrameworkApplication();
builder.Services.AddFrameworkEfCore();
builder.Services.AddRepositoriesForAllEntities<AuthenticationDbContext>();
var app = builder.Build();
3. Authentication Setup
// Configure JWT authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
var jwtConfig = builder.Configuration.GetSection("Jwt").Get<JwtConfiguration>();
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.Key)),
ValidateIssuer = true,
ValidIssuer = jwtConfig.Issuer,
ValidateAudience = true,
ValidAudience = jwtConfig.Audience,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
builder.Services.AddAuthorization();
📊 Domain Model
Entity Relationships
🔌 API Endpoints
Authentication Endpoints
# Login with user login method
POST /api/v1/auth/login
Content-Type: application/json
{
"userLoginMethodId": "550e8400-e29b-41d4-a716-446655440000"
}
# Get user login method by user ID
GET /api/v1/auth/user-login-method/{userId}
Authorization: Bearer {access_token}
User Management Endpoints
# Get all users (paginated)
GET /api/v1/users?page=1&pageSize=20&orderBy=name&orderDirection=asc
Authorization: Bearer {access_token}
# Get user by ID
GET /api/v1/users/{id}
Authorization: Bearer {access_token}
# Create new user
POST /api/v1/users
Content-Type: application/json
{
"name": "John Doe",
"email": "john.doe@example.com",
"phoneNumber": "+1234567890",
"languageCode": "en",
"genderCode": "M"
}
# Update user
PUT /api/v1/users/{id}
Authorization: Bearer {access_token}
Content-Type: application/json
{
"name": "John Smith",
"phoneNumber": "+1234567891"
}
# Verify email
POST /api/v1/users/{id}/verify-email
Authorization: Bearer {access_token}
Content-Type: application/json
{
"verificationCode": "123456"
}
Reference Data Endpoints
# Get all languages
GET /api/v1/languages
# Get all timezones
GET /api/v1/timezones
# Get all genders
GET /api/v1/genders
# Get enabled login methods
GET /api/v1/login-methods/enabled
🎯 Usage Examples
1. Complete Authentication Flow
public class AuthenticationController : ControllerBase
{
private readonly IAuthService _authService;
private readonly IUserService _userService;
[HttpPost("register")]
public async Task<ActionResult<UserDto>> RegisterAsync(CreateUserRequest request)
{
var user = await _userService.CreateUserWithVerificationAsync(request);
return CreatedAtAction(nameof(GetUser), new { id = user.Id }, user);
}
[HttpPost("verify-email")]
public async Task<ActionResult<UserDto>> VerifyEmailAsync(Guid userId, VerifyEmailRequest request)
{
var user = await _userService.VerifyEmailAsync(userId, request.Code);
return Ok(user);
}
[HttpPost("login")]
public async Task<ActionResult<LoginResponse>> LoginAsync(LoginRequest request)
{
var response = await _authService.LoginAsync(request.UserLoginMethodId);
return Ok(response);
}
}
2. Custom User Service Extension
public class ExtendedUserService : UserService
{
private readonly ILogger<ExtendedUserService> _logger;
private readonly IEmailService _emailService;
public override async Task<UserDto> CreateAsync(Guid userId, CreateUserRequest createRequest, CancellationToken ct = default)
{
// Custom validation
if (await Repository.AnyAsync(u => u.Email == createRequest.Email, ct))
throw new BusinessException("Email already exists");
// Create user
var user = await base.CreateAsync(userId, createRequest, ct);
// Send welcome email
await _emailService.SendWelcomeEmailAsync(user.Email, user.Name, ct);
_logger.LogInformation("Created user {UserId} with email {Email}", user.Id, user.Email);
return user;
}
}
3. JWT Token Validation Middleware
public class JwtMiddleware
{
private readonly RequestDelegate _next;
private readonly JwtUtil _jwtUtil;
public async Task InvokeAsync(HttpContext context)
{
var token = context.Request.Headers["Authorization"]
.FirstOrDefault()?.Split(" ").Last();
if (token != null)
{
var principal = _jwtUtil.ValidateAccessToken(token);
if (principal != null)
{
context.User = principal;
}
}
await _next(context);
}
}
📁 Project Structure
MasLazu.AspNet.Authentication.Core/
├── src/
│ ├── MasLazu.AspNet.Authentication.Core.Abstraction/
│ │ ├── Interfaces/
│ │ │ ├── IAuthService.cs
│ │ │ ├── IUserService.cs
│ │ │ └── IGenderService.cs
│ │ ├── Models/
│ │ │ ├── UserDto.cs
│ │ │ ├── LoginResponse.cs
│ │ │ └── CreateUserRequest.cs
│ │ └── MasLazu.AspNet.Authentication.Core.Abstraction.csproj
│ │
│ ├── MasLazu.AspNet.Authentication.Core.Domain/
│ │ ├── Entities/
│ │ │ ├── User.cs
│ │ │ ├── LoginMethod.cs
│ │ │ ├── UserLoginMethod.cs
│ │ │ ├── RefreshToken.cs
│ │ │ └── UserRefreshToken.cs
│ │ └── MasLazu.AspNet.Authentication.Core.Domain.csproj
│ │
│ ├── MasLazu.AspNet.Authentication.Core.Base/
│ │ ├── Services/
│ │ │ ├── AuthService.cs
│ │ │ ├── UserService.cs
│ │ │ └── GenderService.cs
│ │ ├── Utils/
│ │ │ ├── JwtUtil.cs
│ │ │ └── UserEntityPropertyMap.cs
│ │ ├── Configuration/
│ │ │ └── JwtConfiguration.cs
│ │ ├── Extensions/
│ │ │ └── AuthenticationCoreApplicationServiceExtension.cs
│ │ └── MasLazu.AspNet.Authentication.Core.Base.csproj
│ │
│ ├── MasLazu.AspNet.Authentication.Core.Endpoint/
│ │ ├── Endpoints/
│ │ │ ├── Auth/
│ │ │ ├── Users/
│ │ │ └── Reference/
│ │ ├── EndpointGroups/
│ │ │ └── AuthEndpointGroup.cs
│ │ └── MasLazu.AspNet.Authentication.Core.Endpoint.csproj
│ │
│ └── MasLazu.AspNet.Authentication.Core.EfCore/
│ ├── Data/
│ │ └── AuthenticationDbContext.cs
│ ├── Configurations/
│ │ ├── UserConfiguration.cs
│ │ └── LoginMethodConfiguration.cs
│ └── MasLazu.AspNet.Authentication.Core.EfCore.csproj
│
├── MasLazu.AspNet.Authentication.Core.sln
└── README.md
🔗 Dependencies
<!-- Core Framework -->
<PackageReference Include="MasLazu.AspNet.Framework.Application" />
<PackageReference Include="MasLazu.AspNet.Framework.Domain" />
<PackageReference Include="MasLazu.AspNet.Framework.EfCore" />
<PackageReference Include="MasLazu.AspNet.Framework.Endpoint" />
<!-- Authentication -->
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" />
<!-- Validation & Mapping -->
<PackageReference Include="FluentValidation" />
<PackageReference Include="Mapster" />
<!-- Database -->
<PackageReference Include="Microsoft.EntityFrameworkCore" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
<!-- External Services -->
<PackageReference Include="MasLazu.AspNet.Verification.Abstraction" />
✅ Best Practices
✅ Do's
- Use JWT tokens for stateless authentication
- Implement refresh tokens for security
- Validate email/phone before allowing login
- Use secure token generation with proper expiration
- Implement proper error handling for authentication failures
- Use dependency injection for all services
❌ Don'ts
- Don't store sensitive data in JWT payload
- Don't use weak signing keys (minimum 256 bits)
- Don't ignore token expiration validation
- Don't expose internal user IDs in public APIs
- Don't skip input validation on authentication endpoints
🎯 Security Considerations
1. Token Security
// Use strong, random keys
services.Configure<JwtConfiguration>(options =>
{
options.Key = Environment.GetEnvironmentVariable("JWT_KEY") ??
throw new InvalidOperationException("JWT_KEY is required");
});
2. Rate Limiting
services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("AuthPolicy", limiterOptions =>
{
limiterOptions.PermitLimit = 5;
limiterOptions.Window = TimeSpan.FromMinutes(1);
});
});
3. Input Validation
public class CreateUserRequestValidator : AbstractValidator<CreateUserRequest>
{
public CreateUserRequestValidator()
{
RuleFor(x => x.Email)
.NotEmpty()
.EmailAddress()
.MaximumLength(254);
RuleFor(x => x.Name)
.NotEmpty()
.MinimumLength(2)
.MaximumLength(100);
}
}
🎯 Next Steps
After implementing Authentication.Core:
- Verification Module - Email/SMS verification
- Authorization Modules - RBAC, ABAC implementation
- Performance Optimization - Caching and optimization
📚 Related Documentation
- Framework Overview - Core framework concepts
- Modules Overview - Other available modules
- Getting Started - Setup guide