using AutoMapper; using DigitalData.Core.Abstractions.Security; using DigitalData.Core.Security.Config; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; namespace DigitalData.Core.Security { public class JwtSignatureHandler : JwtSecurityTokenHandler, IJwtSignatureHandler { private readonly ClaimDescriptor _claimDescriptor; private readonly IMapper _mapper; private readonly IEnumerable? _tokenDescriptions; private readonly IAsymCryptHandler _cryptHandler; public JwtSignatureHandler(IOptions> claimDescriptorOptions, IMapper mapper, IOptions>? tokenDescriptionOptions, IAsymCryptHandler asymCryptHandler) { _claimDescriptor = claimDescriptorOptions.Value; _mapper = mapper; _tokenDescriptions = tokenDescriptionOptions?.Value; _cryptHandler = asymCryptHandler; } public SecurityToken CreateToken(TPrincipal subject, TokenDescription description) { var descriptor = _mapper.Map(description); descriptor.Claims = _claimDescriptor.CreateClaims?.Invoke(subject); descriptor.Subject = _claimDescriptor.CreateSubject?.Invoke(subject); return CreateToken(descriptor); } public SecurityToken CreateToken(TPrincipal subject, string issuer, string audience) { var description = _tokenDescriptions?.Get(issuer: issuer, audience: audience) ?? throw new InvalidOperationException($"No token description found for issuer '{issuer}' and audience '{audience}'."); description.SigningCredentials = _cryptHandler.Decryptors .Get(issuer: issuer, audience: audience) .CreateSigningCredentials(algorithm: description.SigningAlgorithm, digest: description.SigningDigest); return CreateToken(subject: subject, description: description); } public string CreateAndWriteToken(SecurityTokenDescriptor descriptor) => WriteToken(CreateToken(descriptor)); public string CreateAndWriteToken(TPrincipal subject, TokenDescription description) => WriteToken(CreateToken(subject: subject, description: description)); public string CreateAndWriteToken(TPrincipal subject, string issuer, string audience) => WriteToken(CreateToken(subject: subject, issuer: issuer, audience: audience)); } }