61 lines
2.2 KiB
C#
61 lines
2.2 KiB
C#
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Security.Claims;
|
|
using System.Text;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
|
|
namespace w4c_workflows.Services;
|
|
|
|
/// <summary>
|
|
/// Validates the main w4c JWT (signed with the shared Auth:JwtSigningKey) and
|
|
/// extracts the tenant id. Used exclusively by the /api/keys* surface so a
|
|
/// logged-in tenant can mint/rotate/revoke its own operator keys.
|
|
/// </summary>
|
|
public static class JwtValidator
|
|
{
|
|
static JwtValidator()
|
|
{
|
|
// Keep inbound claims exactly as issued ("tenant_id", "sub", ...).
|
|
// JwtSecurityTokenHandler remaps claims to WS-Federation URIs by
|
|
// default, which makes FindFirstValue("tenant_id") return null.
|
|
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
|
|
}
|
|
|
|
public static ClaimsPrincipal? Validate(
|
|
string? authHeader,
|
|
string signingKey,
|
|
string? issuer = null,
|
|
string? audience = null)
|
|
{
|
|
if (string.IsNullOrEmpty(signingKey) || string.IsNullOrEmpty(authHeader) ||
|
|
!authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
|
return null;
|
|
|
|
try
|
|
{
|
|
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(signingKey));
|
|
var parameters = new TokenValidationParameters
|
|
{
|
|
ValidateIssuerSigningKey = true,
|
|
IssuerSigningKey = key,
|
|
// Issuer/audience are enforced only when the deployment declares
|
|
// them. w4c-auth may not stamp them; a shared symmetric key alone
|
|
// is weaker, so operators are encouraged to set Auth:JwtIssuer /
|
|
// Auth:JwtAudience and get the extra binding.
|
|
ValidateIssuer = !string.IsNullOrWhiteSpace(issuer),
|
|
ValidIssuer = issuer,
|
|
ValidateAudience = !string.IsNullOrWhiteSpace(audience),
|
|
ValidAudience = audience,
|
|
ValidateLifetime = true,
|
|
ClockSkew = TimeSpan.FromMinutes(1),
|
|
};
|
|
|
|
return new JwtSecurityTokenHandler().ValidateToken(
|
|
authHeader["Bearer ".Length..].Trim(), parameters, out _);
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|