Still working on getting client credential flow complete, most of the request works but still working on generating the JWT.

This commit is contained in:
eelke 2026-03-16 19:15:04 +01:00
parent 1a8c63808a
commit 8782ef39c6
80 changed files with 1331 additions and 414 deletions

View file

@ -0,0 +1,10 @@
namespace IdentityShroud.Core.Security.Keys.Aes;
public class AesKeyPolicy : KeyPolicy
{
public AesKeyPolicy()
{
KeyType = KeyType.AES;
KeySize = 256;
}
}

View file

@ -0,0 +1,19 @@
using System.Security.Cryptography;
using IdentityShroud.Core.Messages;
namespace IdentityShroud.Core.Security.Keys.Aes;
public class AesProvider : IKeyProvider
{
public bool IsPublic => false;
public KeyData CreateKey(KeyPolicy policy)
{
return new KeyData(RandomNumberGenerator.GetBytes(policy.KeySize / 8));
}
public void SetJwkParameters(Dictionary<string, string> parameters, JsonWebKey jwk)
{
// Can we use this for Jwe?
throw new NotImplementedException();
}
}

View file

@ -2,17 +2,32 @@ using IdentityShroud.Core.Messages;
namespace IdentityShroud.Core.Security.Keys;
public abstract class KeyPolicy
public class KeyPolicy
{
public abstract string KeyType { get; }
public KeyType KeyType { get; protected init; }
public int KeySize { get; protected init; }
}
public record KeyData(byte[] PrivateKey, Dictionary<string, string>? PublicKeyParameters = null)
{
/// <summary>
/// The data to be kept private, also used for symmetric keys
/// </summary>
public byte[] PrivateKey { get; set; } = PrivateKey;
public Dictionary<string, string>? PublicKeyParameters { get; set; } = PublicKeyParameters;
}
public interface IKeyProvider
{
byte[] CreateKey(KeyPolicy policy);
/// <summary>
/// Returns true when this key uses public key cryptography
/// </summary>
bool IsPublic { get; }
KeyData CreateKey(KeyPolicy policy);
void SetJwkParameters(byte[] key, JsonWebKey jwk);
void SetJwkParameters(Dictionary<string, string> parameters, JsonWebKey jwk);
}

View file

@ -3,5 +3,5 @@ namespace IdentityShroud.Core.Security.Keys;
public interface IKeyProviderFactory
{
public IKeyProvider CreateProvider(string keyType);
public IKeyProvider CreateProvider(KeyType keyType);
}

View file

@ -1,15 +1,18 @@
using IdentityShroud.Core.Security.Keys.Aes;
using IdentityShroud.Core.Security.Keys.Rsa;
namespace IdentityShroud.Core.Security.Keys;
public class KeyProviderFactory : IKeyProviderFactory
{
public IKeyProvider CreateProvider(string keyType)
public IKeyProvider CreateProvider(KeyType keyType)
{
switch (keyType)
switch (keyType.Name)
{
case "RSA":
return new RsaProvider();
case "AES":
return new AesProvider();
default:
throw new NotImplementedException();
}

View file

@ -0,0 +1,21 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace IdentityShroud.Core.Security.Keys;
[JsonConverter(typeof(KeyTypeJsonConverter))]
public readonly record struct KeyType(string Name)
{
public static KeyType AES => new("AES");
public static KeyType RSA => new("RSA");
public override string ToString() => Name;
}
public class KeyTypeJsonConverter : JsonConverter<KeyType>
{
public override KeyType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
=> new KeyType(reader.GetString()!);
public override void Write(Utf8JsonWriter writer, KeyType value, JsonSerializerOptions options)
=> writer.WriteStringValue(value.ToString());
}

View file

@ -0,0 +1,10 @@
namespace IdentityShroud.Core.Security.Keys.Rsa;
public class RsaKeyPolicy : KeyPolicy
{
public RsaKeyPolicy()
{
KeyType = KeyType.RSA;
KeySize = 2048;
}
}

View file

@ -4,32 +4,31 @@ using IdentityShroud.Core.Messages;
namespace IdentityShroud.Core.Security.Keys.Rsa;
public class RsaKeyPolicy : KeyPolicy
{
public override string KeyType => "RSA";
public int KeySize { get; } = 2048;
}
public class RsaProvider : IKeyProvider
{
public byte[] CreateKey(KeyPolicy policy)
public bool IsPublic => true;
public KeyData CreateKey(KeyPolicy policy)
{
if (policy is RsaKeyPolicy p)
{
using var rsa = RSA.Create(p.KeySize);
return rsa.ExportPkcs8PrivateKey();
var publicParamaters = rsa.ExportParameters(includePrivateParameters: false);
return new KeyData(
rsa.ExportPkcs8PrivateKey(),
new()
{
["e"] = Base64Url.EncodeToString(publicParamaters.Exponent),
["n"] = Base64Url.EncodeToString(publicParamaters.Modulus),
});
}
throw new ArgumentException("Incorrect policy type", nameof(policy));
}
public void SetJwkParameters(byte[] key, JsonWebKey jwk)
public void SetJwkParameters(Dictionary<string, string> parameters, JsonWebKey jwk)
{
using var rsa = RSA.Create();
rsa.ImportPkcs8PrivateKey(key, out _);
var parameters = rsa.ExportParameters(includePrivateParameters: false);
jwk.Exponent = Base64Url.EncodeToString(parameters.Exponent);
jwk.Modulus = Base64Url.EncodeToString(parameters.Modulus);
jwk.Exponent = parameters["e"];
jwk.Modulus = parameters["n"];
}
}