Files
ColaFlow/colaflow-api/src/Modules/Identity/ColaFlow.Modules.Identity.Infrastructure/DependencyInjection.cs
Yaojia Wang 1cf0ef0d9c feat(backend): Implement password reset flow (Phase 3)
Complete implementation of secure password reset functionality per DAY7-PRD.md specifications.

Changes:
- Domain: PasswordResetToken entity with 1-hour expiration and single-use constraint
- Domain Events: PasswordResetRequestedEvent and PasswordResetCompletedEvent
- Repository: IPasswordResetTokenRepository with token management and invalidation
- Commands: ForgotPasswordCommand and ResetPasswordCommand with handlers
- Security: MemoryRateLimitService (3 requests/hour) and IRateLimitService interface
- API: POST /api/Auth/forgot-password and POST /api/Auth/reset-password endpoints
- Infrastructure: EF Core configuration and database migration for password_reset_tokens table
- Features: Email enumeration prevention, SHA-256 token hashing, refresh token revocation on password reset
- Test: PowerShell test script for password reset flow verification

Security Enhancements:
- Rate limiting: 3 forgot-password requests per hour per email
- Token security: SHA-256 hashing, 1-hour expiration, single-use only
- Privacy: Always return success message to prevent email enumeration
- Audit trail: IP address and User Agent logging for security monitoring
- Session revocation: All refresh tokens revoked after successful password reset

Database:
- New table: password_reset_tokens with indexes for performance
- Columns: id, user_id, token_hash, expires_at, used_at, ip_address, user_agent, created_at

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 21:47:26 +01:00

68 lines
2.9 KiB
C#

using ColaFlow.Modules.Identity.Application.Services;
using ColaFlow.Modules.Identity.Domain.Repositories;
using ColaFlow.Modules.Identity.Infrastructure.Persistence;
using ColaFlow.Modules.Identity.Infrastructure.Persistence.Repositories;
using ColaFlow.Modules.Identity.Infrastructure.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ColaFlow.Modules.Identity.Infrastructure;
public static class DependencyInjection
{
public static IServiceCollection AddIdentityInfrastructure(
this IServiceCollection services,
IConfiguration configuration,
IHostEnvironment? environment = null)
{
// Only register PostgreSQL DbContext in non-Testing environments
// In Testing environment, WebApplicationFactory will register InMemory provider
if (environment == null || environment.EnvironmentName != "Testing")
{
// DbContext (using connection string)
services.AddDbContext<IdentityDbContext>(options =>
options.UseNpgsql(
configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly(typeof(IdentityDbContext).Assembly.FullName)));
}
// Tenant Context (Scoped - one instance per request)
services.AddScoped<ITenantContext, TenantContext>();
services.AddHttpContextAccessor(); // Required for HttpContext access
// Repositories
services.AddScoped<ITenantRepository, TenantRepository>();
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IRefreshTokenRepository, RefreshTokenRepository>();
services.AddScoped<IUserTenantRoleRepository, UserTenantRoleRepository>();
services.AddScoped<IEmailVerificationTokenRepository, EmailVerificationTokenRepository>();
services.AddScoped<IPasswordResetTokenRepository, PasswordResetTokenRepository>();
// Application Services
services.AddScoped<IJwtService, JwtService>();
services.AddScoped<IPasswordHasher, PasswordHasher>();
services.AddScoped<IRefreshTokenService, RefreshTokenService>();
services.AddScoped<ISecurityTokenService, SecurityTokenService>();
// Memory cache for rate limiting
services.AddMemoryCache();
services.AddSingleton<IRateLimitService, MemoryRateLimitService>();
// Email Services
var emailProvider = configuration["Email:Provider"] ?? "Mock";
if (emailProvider.Equals("Mock", StringComparison.OrdinalIgnoreCase))
{
services.AddSingleton<IEmailService, MockEmailService>();
}
else
{
services.AddScoped<IEmailService, SmtpEmailService>();
}
services.AddScoped<IEmailTemplateService, EmailTemplateService>();
return services;
}
}