Extracts the authenticated sender's integer ID from the 'sub' / NameIdentifier claim. Mirrors the existing ReceiverId() helper and is required by GetDocumentOfSenderAsync.
123 lines
4.7 KiB
C#
123 lines
4.7 KiB
C#
using DigitalData.Auth.Claims;
|
|
using DigitalData.UserManager.Domain.Entities;
|
|
using EnvelopeGenerator.Domain.Constants;
|
|
using Microsoft.IdentityModel.JsonWebTokens;
|
|
using System.Security.Claims;
|
|
|
|
namespace EnvelopeGenerator.Server.Extensions;
|
|
|
|
/// <summary>
|
|
/// Provides helper methods for working with envelope-specific authentication claims.
|
|
/// </summary>
|
|
public static class ReceiverClaimExtensions
|
|
{
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="user"></param>
|
|
/// <param name="claimType"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="InvalidOperationException"></exception>
|
|
private static string GetRequiredClaimValue(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 GetRequiredClaimValue(this ClaimsPrincipal user, params string[] claimTypes)
|
|
{
|
|
foreach (var claimType in claimTypes.Where(t => !string.IsNullOrWhiteSpace(t)).Distinct())
|
|
{
|
|
var value = user.FindFirstValue(claimType);
|
|
if (!string.IsNullOrWhiteSpace(value))
|
|
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(s) '{string.Join("', '", claimTypes)}' are missing for user '{principalName}' (auth: {authType}). Available claims: [{availableClaims}].";
|
|
throw new InvalidOperationException(message);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the authenticated envelope UUID from the claims.
|
|
/// </summary>
|
|
public static string EnvelopeUuid(this ClaimsPrincipal user)
|
|
=> user.GetRequiredClaimValue(EnvelopeClaimNames.EnvelopeUuid);
|
|
|
|
/// <summary>
|
|
/// Gets the authenticated receiver signature from the claims.
|
|
/// </summary>
|
|
public static string ReceiverSignature(this ClaimsPrincipal user)
|
|
=> user.GetRequiredClaimValue(EnvelopeClaimNames.ReceiverSignature);
|
|
|
|
/// <summary>
|
|
/// Gets the authenticated receiver email address from the claims.
|
|
/// </summary>
|
|
public static string ReceiverMail(this ClaimsPrincipal user)
|
|
=> user.GetRequiredClaimValue(JwtRegisteredClaimNames.Email);
|
|
|
|
/// <summary>
|
|
/// Gets the authenticated envelope identifier from the claims.
|
|
/// </summary>
|
|
public static int EnvelopeId(this ClaimsPrincipal user)
|
|
{
|
|
var envIdStr = user.GetRequiredClaimValue(EnvelopeClaimNames.EnvelopeId);
|
|
if (int.TryParse(envIdStr, out var envId))
|
|
return envId;
|
|
else
|
|
throw new InvalidOperationException($"Claim '{EnvelopeClaimNames.EnvelopeId}' is not a valid integer.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the authenticated receiver identifier from the claims.
|
|
/// </summary>
|
|
/// <param name="user"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="InvalidOperationException"></exception>
|
|
public static int ReceiverId(this ClaimsPrincipal user)
|
|
{
|
|
var rcvIdStr = user.GetRequiredClaimValue(EnvelopeClaimNames.ReceiverId);
|
|
if (int.TryParse(rcvIdStr, out var rcvId))
|
|
return rcvId;
|
|
else
|
|
throw new InvalidOperationException($"Claim '{EnvelopeClaimNames.ReceiverId}' is not a valid integer.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the authenticated sender identifier from the 'sub' claim.
|
|
/// </summary>
|
|
/// <param name="user"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="InvalidOperationException"></exception>
|
|
public static int SenderId(this ClaimsPrincipal user)
|
|
{
|
|
var senderIdStr = user.GetRequiredClaimValue(JwtRegisteredClaimNames.Sub, ClaimTypes.NameIdentifier);
|
|
if (int.TryParse(senderIdStr, out var senderId))
|
|
return senderId;
|
|
else
|
|
throw new InvalidOperationException($"Claim '{JwtRegisteredClaimNames.Sub}' is not a valid integer.");
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="user"></param>
|
|
/// <returns></returns>
|
|
public static bool IsReceiver(this ClaimsPrincipal user)
|
|
{
|
|
return Role.Receiver.Authorized.Any(user.IsInRole);
|
|
}
|
|
} |