using DigitalData.Core.Abstractions.Security.Common; using DigitalData.Core.Abstractions.Security.Key; using DigitalData.Core.Abstractions.Security.Services; using Microsoft.IdentityModel.Tokens; using System.Text; namespace DigitalData.Core.Abstractions.Security.Extensions; public static class SecurityExtensions { #region Unique Security Context public static IEnumerable GetByIssuer(this IEnumerable contextes, string issuer) where TUniqueSecurityContext : IUniqueSecurityContext => contextes.Where(c => c.Issuer == issuer); public static IEnumerable GetByAudience(this IEnumerable contextes, string audience) where TUniqueSecurityContext : IUniqueSecurityContext => contextes.Where(c => c.Audience == audience); public static TUniqueSecurityContext Get(this IEnumerable contextes, string issuer, string audience) where TUniqueSecurityContext : IUniqueSecurityContext => contextes.Where(c => c.Issuer == issuer && c.Audience == audience).SingleOrDefault() ?? throw new InvalidOperationException($"Exactly one {typeof(TUniqueSecurityContext).Name} must exist with Issuer: '{issuer}' and Audience: '{audience}'."); public static bool TryGet(this IEnumerable contextes, string issuer, string audience, out TUniqueSecurityContext context) where TUniqueSecurityContext : IUniqueSecurityContext { #pragma warning disable CS8601 // Possible null reference assignment. context = contextes.SingleOrDefault(c => c.Issuer == issuer && c.Audience == audience); #pragma warning restore CS8601 // Possible null reference assignment. return context is not null; } public static TUniqueSecurityContext Match(this IEnumerable contextes, IUniqueSecurityContext lookupContext) where TUniqueSecurityContext : IUniqueSecurityContext => contextes.Get(lookupContext.Issuer, lookupContext.Audience); public static bool TryMatch(this IEnumerable contextes, IUniqueSecurityContext lookupContext, out TUniqueSecurityContext context) where TUniqueSecurityContext : IUniqueSecurityContext => contextes.TryGet(lookupContext.Issuer, lookupContext.Audience, out context); #endregion Unique Security Context #region De/serilization internal static byte[] Base64ToByte(this string base64String) => Convert.FromBase64String(base64String); internal static string BytesToString(this byte[] bytes) => Encoding.UTF8.GetString(bytes); internal static string ToBase64String(this byte[] bytes) => Convert.ToBase64String(bytes); internal static byte[] ToBytes(this string str) => Encoding.UTF8.GetBytes(str); public static string Decrypt(this IAsymmetricDecryptor decryptor, string data) => decryptor .Decrypt(data.Base64ToByte()).BytesToString(); #endregion De/serilization #region Asymmetric Encryptor public static string Encrypt(this IAsymmetricEncryptor encryptor, string data) => encryptor.Encrypt(data.ToBytes()).ToBase64String(); #endregion Asymmetric Encryptor #region Jwt Signature Handler public static string WriteToken(this IJwtSignatureHandler handler, SecurityTokenDescriptor descriptor) => handler.WriteToken(handler.CreateToken(descriptor)); public static string WriteToken(this IJwtSignatureHandler handler, TPrincipal subject, IAsymmetricTokenDescriptor descriptor) => handler.WriteToken(handler.CreateToken(subject: subject, descriptor: descriptor)); public static string WriteToken(this IJwtSignatureHandler handler, TPrincipal subject, string issuer, string audience) => handler.WriteToken(handler.CreateToken(subject: subject, issuer: issuer, audience: audience)); #endregion Jwt Signature Handler }