119 lines
5.7 KiB
C#
119 lines
5.7 KiB
C#
using DigitalData.Core.Abstractions.Security;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
|
|
namespace DigitalData.Core.Security.RSAKey
|
|
{
|
|
/// <summary>
|
|
/// Contains some information which used to create a security token. Designed to abstract <see cref="SecurityTokenDescriptor"/>
|
|
/// </summary>
|
|
public class RSATokenDescriptor : RSAPrivateKey, IAsymmetricTokenDescriptor
|
|
{
|
|
internal string IdSeparator { get; set; } = "_-_";
|
|
|
|
private string? _id;
|
|
|
|
public override string Id { get => _id ?? $"{Issuer}{IdSeparator}{Audience}"; internal set => _id = value; }
|
|
|
|
public string? ApiRoute { get; init; }
|
|
|
|
#region SecurityTokenDescriptor Map
|
|
/// <summary>
|
|
/// Gets or sets the value of the 'audience' claim.
|
|
/// </summary>
|
|
public required string Audience { get; set; }
|
|
|
|
/// <summary>
|
|
/// Defines the compression algorithm that will be used to compress the JWT token payload.
|
|
/// </summary>
|
|
public string CompressionAlgorithm { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the <see cref="EncryptingCredentials"/> used to create a encrypted security token.
|
|
/// </summary>
|
|
public EncryptingCredentials EncryptingCredentials { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the value of the 'expiration' claim. This value should be in UTC.
|
|
/// </summary>
|
|
public DateTime? Expires { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the issuer of this <see cref="SecurityTokenDescriptor"/>.
|
|
/// </summary>
|
|
public required string Issuer { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the time the security token was issued. This value should be in UTC.
|
|
/// </summary>
|
|
public DateTime? IssuedAt { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the notbefore time for the security token. This value should be in UTC.
|
|
/// </summary>
|
|
public DateTime? NotBefore { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the token type.
|
|
/// <remarks> If provided, this will be added as the value for the 'typ' header parameter. In the case of a JWE, this will be added to both the inner (JWS) and the outer token (JWE) header. By default, the value used is 'JWT'.
|
|
/// If <see cref="AdditionalHeaderClaims"/> also contains 'typ' header claim value, it will override the TokenType provided here.
|
|
/// This value is used only for JWT tokens and not for SAML/SAML2 tokens</remarks>
|
|
/// </summary>
|
|
public string TokenType { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the <see cref="Dictionary{TKey, TValue}"/> which contains any custom header claims that need to be added to the JWT token header.
|
|
/// The 'alg', 'kid', 'x5t', 'enc', and 'zip' claims are added by default based on the <see cref="SigningCredentials"/>,
|
|
/// <see cref="EncryptingCredentials"/>, and/or <see cref="CompressionAlgorithm"/> provided and SHOULD NOT be included in this dictionary as this
|
|
/// will result in an exception being thrown.
|
|
/// <remarks> These claims are only added to the outer header (in case of a JWE).</remarks>
|
|
/// </summary>
|
|
public IDictionary<string, object> AdditionalHeaderClaims { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the <see cref="Dictionary{TKey, TValue}"/> which contains any custom header claims that need to be added to the inner JWT token header.
|
|
/// The 'alg', 'kid', 'x5t', 'enc', and 'zip' claims are added by default based on the <see cref="SigningCredentials"/>,
|
|
/// <see cref="EncryptingCredentials"/>, and/or <see cref="CompressionAlgorithm"/> provided and SHOULD NOT be included in this dictionary as this
|
|
/// will result in an exception being thrown.
|
|
/// <remarks>
|
|
/// For JsonWebTokenHandler, these claims are merged with <see cref="AdditionalHeaderClaims"/> while adding to the inner JWT header.
|
|
/// </remarks>
|
|
/// </summary>
|
|
public IDictionary<string, object> AdditionalInnerHeaderClaims { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the <see cref="SigningCredentials"/> used to create a security token.
|
|
/// </summary>
|
|
public SigningCredentials SigningCredentials => _lazySigningCredentials.Value;
|
|
#endregion SecurityTokenDescriptor
|
|
|
|
private readonly Lazy<RsaSecurityKey> _lazyRsaSecurityKey;
|
|
|
|
public SecurityKey SecurityKey => _lazyRsaSecurityKey.Value;
|
|
|
|
private readonly Lazy<SigningCredentials> _lazySigningCredentials;
|
|
|
|
/// <summary>
|
|
/// Specifies the signature algorithm to be applied to the <see cref="SigningCredentials"/>.
|
|
/// Default is <see cref="SecurityAlgorithms.RsaSha256"/>.
|
|
/// </summary>
|
|
public string SigningAlgorithm { get; init; } = SecurityAlgorithms.RsaSha256;
|
|
|
|
/// <summary>
|
|
/// Optionally specifies the digest algorithm to be applied during the signing process for the <see cref="SigningCredentials"/>.
|
|
/// If not provided, the default algorithm is used.
|
|
/// </summary>
|
|
public string? SigningDigest { get; init; }
|
|
|
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
|
public RSATokenDescriptor()
|
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
|
{
|
|
_lazyRsaSecurityKey = new(() => new RsaSecurityKey(RSA));
|
|
|
|
_lazySigningCredentials = new(() => SigningDigest is null
|
|
? new(SecurityKey, SigningAlgorithm)
|
|
: new(SecurityKey, SigningAlgorithm, SigningDigest));
|
|
}
|
|
}
|
|
}
|