using System.Security.Claims; namespace EnvelopeGenerator.API.Extensions { /// /// Provides extension methods for extracting user information from a . /// public static class SenderClaimExtensions { private static string GetRequiredClaimOfSender(this ClaimsPrincipal user, string claimType) { var value = user.FindFirstValue(claimType); if (value is not null) { return value; } var identity = user.Identity; var principalName = identity?.Name ?? "(anonymous)"; var authType = identity?.AuthenticationType ?? "(none)"; var availableClaims = string.Join(", ", user.Claims.Select(c => $"{c.Type}={c.Value}")); var message = $"Required claim '{claimType}' is missing for user '{principalName}' (auth: {authType}). Available claims: [{availableClaims}]."; throw new InvalidOperationException(message); } private static string GetRequiredClaimOfSender(this ClaimsPrincipal user, params string[] claimTypes) { string? value = null; foreach (var claimType in claimTypes) { value = user.FindFirstValue(claimType); if (value is not null) return value; } var identity = user.Identity; var principalName = identity?.Name ?? "(anonymous)"; var authType = identity?.AuthenticationType ?? "(none)"; var availableClaims = string.Join(", ", user.Claims.Select(c => $"{c.Type}={c.Value}")); var message = $"Required claim among [{string.Join(", ", claimTypes)}] is missing for user '{principalName}' (auth: {authType}). Available claims: [{availableClaims}]."; throw new InvalidOperationException(message); } /// /// Retrieves the user's ID from the claims. Throws an exception if the ID is missing or invalid. /// /// The representing the user. /// The user's ID as an integer. /// Thrown if the user ID claim is missing or invalid. public static int GetId(this ClaimsPrincipal user) { var idValue = user.GetRequiredClaimOfSender(ClaimTypes.NameIdentifier, "sub"); if (!int.TryParse(idValue, out var result)) { throw new InvalidOperationException("User ID claim is missing or invalid. This may indicate a misconfigured or forged JWT token."); } return result; } /// /// Retrieves the username from the claims. /// /// The representing the user. /// The username as a string. public static string GetUsername(this ClaimsPrincipal user) => user.GetRequiredClaimOfSender(ClaimTypes.Name); /// /// Retrieves the user's surname (last name) from the claims. /// /// The representing the user. /// The surname as a string. public static string GetName(this ClaimsPrincipal user) => user.GetRequiredClaimOfSender(ClaimTypes.Surname); /// /// Retrieves the user's given name (first name) from the claims. /// /// The representing the user. /// The given name as a string. public static string GetPrename(this ClaimsPrincipal user) => user.GetRequiredClaimOfSender(ClaimTypes.GivenName); /// /// Retrieves the user's email address from the claims. /// /// The representing the user. /// The email address as a string. public static string GetEmail(this ClaimsPrincipal user) => user.GetRequiredClaimOfSender(ClaimTypes.Email); } }