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>
78 lines
3.1 KiB
PowerShell
78 lines
3.1 KiB
PowerShell
# Test Password Reset Flow
|
|
# This script tests the complete password reset functionality
|
|
|
|
$baseUrl = "http://localhost:5266/api"
|
|
|
|
Write-Host "========================================" -ForegroundColor Cyan
|
|
Write-Host "Testing Password Reset Flow" -ForegroundColor Cyan
|
|
Write-Host "========================================" -ForegroundColor Cyan
|
|
Write-Host ""
|
|
|
|
# Step 1: Request password reset
|
|
Write-Host "[Step 1] Requesting password reset for test user..." -ForegroundColor Yellow
|
|
$forgotPasswordRequest = @{
|
|
email = "test@example.com"
|
|
tenantSlug = "acme"
|
|
} | ConvertTo-Json
|
|
|
|
try {
|
|
$forgotPasswordResponse = Invoke-RestMethod -Uri "$baseUrl/Auth/forgot-password" `
|
|
-Method Post `
|
|
-Body $forgotPasswordRequest `
|
|
-ContentType "application/json" `
|
|
-ErrorAction Stop
|
|
|
|
Write-Host "SUCCESS: Password reset email requested" -ForegroundColor Green
|
|
Write-Host "Response: $($forgotPasswordResponse.message)" -ForegroundColor Gray
|
|
Write-Host ""
|
|
} catch {
|
|
Write-Host "FAILED: Password reset request failed" -ForegroundColor Red
|
|
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
|
|
# Step 2: Note about email
|
|
Write-Host "[Step 2] Check email for reset token" -ForegroundColor Yellow
|
|
Write-Host "In a real scenario, you would:" -ForegroundColor Gray
|
|
Write-Host " 1. Check your email inbox" -ForegroundColor Gray
|
|
Write-Host " 2. Click the password reset link" -ForegroundColor Gray
|
|
Write-Host " 3. Enter a new password" -ForegroundColor Gray
|
|
Write-Host ""
|
|
Write-Host "Since we're using MockEmailService, check the console logs." -ForegroundColor Gray
|
|
Write-Host ""
|
|
|
|
# Step 3: Test with invalid token (for security verification)
|
|
Write-Host "[Step 3] Testing with invalid reset token (security check)..." -ForegroundColor Yellow
|
|
$invalidResetRequest = @{
|
|
token = "invalid-token-12345"
|
|
newPassword = "NewPassword123!"
|
|
} | ConvertTo-Json
|
|
|
|
try {
|
|
$invalidResetResponse = Invoke-RestMethod -Uri "$baseUrl/Auth/reset-password" `
|
|
-Method Post `
|
|
-Body $invalidResetRequest `
|
|
-ContentType "application/json" `
|
|
-ErrorAction Stop
|
|
|
|
Write-Host "UNEXPECTED: Invalid token should have been rejected" -ForegroundColor Red
|
|
} catch {
|
|
$statusCode = $_.Exception.Response.StatusCode.value__
|
|
if ($statusCode -eq 400) {
|
|
Write-Host "SUCCESS: Invalid token correctly rejected (400 Bad Request)" -ForegroundColor Green
|
|
} else {
|
|
Write-Host "FAILED: Unexpected status code: $statusCode" -ForegroundColor Red
|
|
}
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "========================================" -ForegroundColor Cyan
|
|
Write-Host "Test Summary" -ForegroundColor Cyan
|
|
Write-Host "========================================" -ForegroundColor Cyan
|
|
Write-Host "1. Forgot password request: SUCCESS" -ForegroundColor Green
|
|
Write-Host "2. Invalid token handling: SUCCESS" -ForegroundColor Green
|
|
Write-Host "3. To complete the test:" -ForegroundColor Yellow
|
|
Write-Host " - Extract the token from email logs" -ForegroundColor Gray
|
|
Write-Host " - Call POST /api/Auth/reset-password with valid token" -ForegroundColor Gray
|
|
Write-Host ""
|