forked from gongxuegit/tiku-backend.net
feat: harden SaaS authentication and authorization
This commit is contained in:
59
Tiku.Infrastructure/Auth/JwtKeyRing.cs
Normal file
59
Tiku.Infrastructure/Auth/JwtKeyRing.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System.Security.Cryptography;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Tiku.Application.Security;
|
||||
|
||||
namespace Tiku.Infrastructure.Auth;
|
||||
|
||||
internal sealed class JwtKeyRing : IJwtKeyRing, IDisposable
|
||||
{
|
||||
private readonly List<RSA> keys = [];
|
||||
|
||||
public JwtKeyRing(IOptions<JwtOptions> options)
|
||||
{
|
||||
var value = options.Value;
|
||||
var signingRsa = RSA.Create(3072);
|
||||
keys.Add(signingRsa);
|
||||
if (!string.IsNullOrWhiteSpace(value.PrivateKeyPem))
|
||||
{
|
||||
signingRsa.ImportFromPem(value.PrivateKeyPem);
|
||||
}
|
||||
|
||||
var signingKey = CreateKey(signingRsa, value.KeyId);
|
||||
SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha256);
|
||||
|
||||
var validationKeys = new List<SecurityKey> { signingKey };
|
||||
foreach (var pair in value.PublicKeys.Where(pair => pair.Key != value.KeyId))
|
||||
{
|
||||
var rsa = RSA.Create();
|
||||
rsa.ImportFromPem(pair.Value);
|
||||
keys.Add(rsa);
|
||||
validationKeys.Add(CreateKey(rsa, pair.Key));
|
||||
}
|
||||
|
||||
ValidationKeys = validationKeys;
|
||||
}
|
||||
|
||||
public SigningCredentials SigningCredentials { get; }
|
||||
public IReadOnlyCollection<SecurityKey> ValidationKeys { get; }
|
||||
|
||||
private static RsaSecurityKey CreateKey(RSA rsa, string keyId) => new(rsa)
|
||||
{
|
||||
KeyId = keyId,
|
||||
// IdentityModel caches signature providers globally by key identity. A key ring owns
|
||||
// and disposes its RSA instances, so a provider retained by another in-process host
|
||||
// could otherwise reference an RSA instance that has already been disposed.
|
||||
CryptoProviderFactory = new CryptoProviderFactory
|
||||
{
|
||||
CacheSignatureProviders = false
|
||||
}
|
||||
};
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var key in keys)
|
||||
{
|
||||
key.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user