Refactor claim accessors to enforce required claims
Refactored EnvelopeAuthExtensions to require presence of all key authentication claims. Added GetRequiredClaim helper that throws detailed exceptions if claims are missing or invalid, replacing nullable return types with non-nullable ones. This ensures authentication logic fails fast and provides clearer error messages when claims are misconfigured or tampered with.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
@@ -10,46 +11,67 @@ namespace EnvelopeGenerator.API.Extensions;
|
||||
/// </summary>
|
||||
public static class EnvelopeAuthExtensions
|
||||
{
|
||||
private static string GetRequiredClaim(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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a claim value by type.
|
||||
/// </summary>
|
||||
/// <param name="user">The current claims principal.</param>
|
||||
/// <param name="claimType">The claim type to resolve.</param>
|
||||
/// <returns>The claim value or null when missing.</returns>
|
||||
public static string? GetClaimValue(this ClaimsPrincipal user, string claimType) => user.FindFirstValue(claimType);
|
||||
/// <returns>The claim value.</returns>
|
||||
public static string GetClaimValue(this ClaimsPrincipal user, string claimType) => user.GetRequiredClaim(claimType);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authenticated envelope UUID from the claims.
|
||||
/// </summary>
|
||||
public static string? GetAuthEnvelopeUuid(this ClaimsPrincipal user) => user.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
public static string GetAuthEnvelopeUuid(this ClaimsPrincipal user) => user.GetRequiredClaim(ClaimTypes.NameIdentifier);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authenticated receiver signature from the claims.
|
||||
/// </summary>
|
||||
public static string? GetAuthReceiverSignature(this ClaimsPrincipal user) => user.FindFirstValue(ClaimTypes.Hash);
|
||||
public static string GetAuthReceiverSignature(this ClaimsPrincipal user) => user.GetRequiredClaim(ClaimTypes.Hash);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authenticated receiver display name from the claims.
|
||||
/// </summary>
|
||||
public static string? GetAuthReceiverName(this ClaimsPrincipal user) => user.FindFirstValue(ClaimTypes.Name);
|
||||
public static string GetAuthReceiverName(this ClaimsPrincipal user) => user.GetRequiredClaim(ClaimTypes.Name);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authenticated receiver email address from the claims.
|
||||
/// </summary>
|
||||
public static string? GetAuthReceiverMail(this ClaimsPrincipal user) => user.FindFirstValue(ClaimTypes.Email);
|
||||
public static string GetAuthReceiverMail(this ClaimsPrincipal user) => user.GetRequiredClaim(ClaimTypes.Email);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authenticated envelope title from the claims.
|
||||
/// </summary>
|
||||
public static string? GetAuthEnvelopeTitle(this ClaimsPrincipal user) => user.FindFirstValue(EnvelopeClaimTypes.Title);
|
||||
public static string GetAuthEnvelopeTitle(this ClaimsPrincipal user) => user.GetRequiredClaim(EnvelopeClaimTypes.Title);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authenticated envelope identifier from the claims.
|
||||
/// </summary>
|
||||
public static int? GetAuthEnvelopeId(this ClaimsPrincipal user)
|
||||
public static int GetAuthEnvelopeId(this ClaimsPrincipal user)
|
||||
{
|
||||
var envIdStr = user.FindFirstValue(EnvelopeClaimTypes.Id);
|
||||
return int.TryParse(envIdStr, out var envId) ? envId : null;
|
||||
var envIdStr = user.GetRequiredClaim(EnvelopeClaimTypes.Id);
|
||||
if (!int.TryParse(envIdStr, out var envId))
|
||||
{
|
||||
throw new InvalidOperationException($"Claim '{EnvelopeClaimTypes.Id}' is not a valid integer.");
|
||||
}
|
||||
|
||||
return envId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -84,4 +106,4 @@ public static class EnvelopeAuthExtensions
|
||||
new ClaimsPrincipal(claimsIdentity),
|
||||
authProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user