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 ICryptograph _cryptograph; public JwtSignatureHandler(IOptions> claimDescriptorOptions, IMapper mapper, ICryptograph cryptograph) { _claimDescriptor = claimDescriptorOptions.Value; _mapper = mapper; _cryptograph = cryptograph; } public SecurityToken CreateToken(TPrincipal subject, IAsymmetricTokenDescriptor descriptor) { var sDescriptor = _mapper.Map(descriptor); sDescriptor.Claims = _claimDescriptor.CreateClaims?.Invoke(subject); sDescriptor.Subject = _claimDescriptor.CreateSubject?.Invoke(subject); return CreateToken(sDescriptor); } public SecurityToken CreateToken(TPrincipal subject, string issuer, string audience) { var descriptor = _cryptograph.TokenDescriptors.Get(issuer: issuer, audience: audience) ?? throw new InvalidOperationException($"No or multiple token description found for issuer '{issuer}' and audience '{audience}'."); return CreateToken(subject: subject, descriptor: descriptor); } public SecurityToken CreateToken(TPrincipal subject, string apiRoute) { var desc = _cryptograph.TokenDescriptors.SingleOrDefault(desc => desc.ApiRoute == apiRoute) ?? throw new InvalidOperationException($"No or multiple token description found for api route '{apiRoute}'."); return CreateToken(subject: subject, descriptor: desc); } public string WriteToken(SecurityTokenDescriptor descriptor) => WriteToken(CreateToken(descriptor)); public string WriteToken(TPrincipal subject, IAsymmetricTokenDescriptor descriptor) => WriteToken(CreateToken(subject: subject, descriptor: descriptor)); public string WriteToken(TPrincipal subject, string issuer, string audience) => WriteToken(CreateToken(subject: subject, issuer: issuer, audience: audience)); public string WriteToken(TPrincipal subject, string apiRoute) => WriteToken(CreateToken(subject: subject, apiRoute: apiRoute)); } }