using System.IdentityModel.Tokens.Jwt; using System.Net.Http.Json; using System.Security.Claims; namespace ColaFlow.Modules.Identity.IntegrationTests.Infrastructure; /// /// Helper class for authentication-related test operations /// Provides utilities for registration, login, token parsing, and common test scenarios /// public static class TestAuthHelper { /// /// Register a new tenant and return the access token and refresh token /// public static async Task<(string accessToken, string refreshToken)> RegisterAndGetTokensAsync( HttpClient client, string? tenantSlug = null, string? email = null, string? password = null) { var slug = tenantSlug ?? $"test-{Guid.NewGuid():N}"; var adminEmail = email ?? $"admin-{Guid.NewGuid():N}@test.com"; var adminPassword = password ?? "Admin@1234"; var request = new { tenantName = "Test Corp", tenantSlug = slug, subscriptionPlan = "Professional", adminEmail, adminPassword, adminFullName = "Test Admin" }; var response = await client.PostAsJsonAsync("/api/tenants/register", request); response.EnsureSuccessStatusCode(); var result = await response.Content.ReadFromJsonAsync(); return (result!.AccessToken, result.RefreshToken); } /// /// Login with credentials and return tokens /// public static async Task<(string accessToken, string refreshToken)> LoginAndGetTokensAsync( HttpClient client, string tenantSlug, string email, string password) { var request = new { tenantSlug, email, password }; var response = await client.PostAsJsonAsync("/api/auth/login", request); response.EnsureSuccessStatusCode(); var result = await response.Content.ReadFromJsonAsync(); return (result!.AccessToken, result.RefreshToken); } /// /// Parse JWT token and extract claims /// public static IEnumerable ParseJwtToken(string token) { var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadJwtToken(token); return jwtToken.Claims; } /// /// Get specific claim value from token /// public static string? GetClaimValue(string token, string claimType) { var claims = ParseJwtToken(token); return claims.FirstOrDefault(c => c.Type == claimType)?.Value; } /// /// Verify token contains expected role /// public static bool HasRole(string token, string role) { var claims = ParseJwtToken(token); return claims.Any(c => c.Type == "role" && c.Value == role) || claims.Any(c => c.Type == "tenant_role" && c.Value == role); } /// /// Extract invitation token from email HTML body /// public static string? ExtractInvitationTokenFromEmail(string htmlBody) { return ExtractTokenFromEmailBody(htmlBody, "token"); } /// /// Extract verification token from email HTML body /// public static string? ExtractVerificationTokenFromEmail(string htmlBody) { return ExtractTokenFromEmailBody(htmlBody, "token"); } /// /// Extract password reset token from email HTML body /// public static string? ExtractPasswordResetTokenFromEmail(string htmlBody) { return ExtractTokenFromEmailBody(htmlBody, "token"); } /// /// Extract token from email HTML body by parameter name /// private static string? ExtractTokenFromEmailBody(string htmlBody, string tokenParam) { // Pattern to match: token=VALUE or ?token=VALUE or &token=VALUE var pattern = $@"[?&]{tokenParam}=([A-Za-z0-9_-]+)"; var match = System.Text.RegularExpressions.Regex.Match(htmlBody, pattern); return match.Success ? match.Groups[1].Value : null; } } // Response DTOs public record RegisterResponse(string AccessToken, string RefreshToken); public record LoginResponse(string AccessToken, string RefreshToken); public record RefreshResponse(string AccessToken, string RefreshToken); public record UserInfoResponse( string UserId, string TenantId, string Email, string FullName, string TenantSlug, string TenantRole);