使用带有 DataProtection API 的 IdentityServer4 进行令牌签名
Using IdentityServer4 with DataProtection API for token signing
我有一个基于 IS4 + Net Core 3.1 的 authentication/authorization 服务器。
由于此身份服务与一些新的以及一些非常旧的应用程序交互,它还会创建 2 个不同的身份验证 cookie 和令牌。
我们目前正在使用 DPAPI 来签署 cookie 和我们需要的其他一些敏感信息。
到目前为止,我们一直在使用证书作为 IS4 中的 SigningCredential,但现在我希望能够使用 DPAPI 以便自动管理密钥轮换,或者至少,我们可以在一个一个地方。
基于IS4 docs我只需要实现ISigningCredentialStore
和IValidationKeysStore
,但是我不太熟悉这是如何管理的。
我有这样的近似值(我知道,此时它几乎毫无价值):
private class CustomSigningCredentialStore : ISigningCredentialStore
{
private readonly IKeyManager _keyManager;
public CustomSigningCredentialStore(IKeyManager keyManager) =>
_keyManager = keyManager;
public Task<SigningCredentials> GetSigningCredentialsAsync()
{
// For the sake of simplicity, lets assume
// that this is the correct one
var currentKey = _keyManager.GetAllKeys().ElementAt(0);
// Complete
return new SigningCredentials(...);
}
}
private class CustomValidationKeysStore : IValidationKeysStore
{
private readonly IKeyManager _keyManager;
public CustomValidationKeysStore(IKeyManager keyManager) =>
_keyManager = keyManager;
public Task<IEnumerable<SecurityKeyInfo>> GetValidationKeysAsync()
{
var keys = _keyManager.GetAllKeys();
// Complete
return keys.Select(key => new SecurityKeyInfo(...));
}
}
老实说,我被这个问题困住了,我不知道如何映射由 DPAPI 生成的当前密钥,它看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<key id="32f6d43e-97a9-4c4b-b108-e11f65e05cc4" version="1">
<creationDate>2020-07-31T00:00:00.0886417Z</creationDate>
<activationDate>2020-07-31T00:00:00.086065Z</activationDate>
<expirationDate>2020-08-30T00:00:00.086065Z</expirationDate>
<descriptor deserializerType="Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=3.1.8.0, Culture=neutral, PublicKeyToken=adb9793829ddae60">
<descriptor>
<encryption algorithm="AES_256_CBC" />
<validation algorithm="HMACSHA256" />
<masterKey p4:requiresEncryption="true" xmlns:p4="http://schemas.asp.net/2015/03/dataProtection">
<value>h1/a9G8i78kpnHBTEsisA5rk5ppm8vzByquAT2CO1OFnYHCX/eT/yfcFM/JigYkSDj+dupBz9ZZ7/XFMu/uWxg==</value>
</masterKey>
</descriptor>
</descriptor>
</key>
任何见解将不胜感激。
我最近实现了自己的 key-ring 存储,将密钥存储在 Azure Key Vault 中,我在此处发布了相关博客:
Storing the ASP.NET Core Data Protection Key Ring in Azure Key Vault
对于您询问的令牌登录,我首先从 Azure Key Vault 加载它们,然后将其手动添加到 IdentitySever,就像这样(使用一些自定义扩展方法):
// First we load the certificates (that contains the private keys) from Azure Key Vault
var rsaCert = KeyVaultExtensions.LoadCertificate(config, "rsa");
//Add RS256 (RSASSA-PKCS1-v1_5 using SHA-256)
builder.AddSigningCredential(rsaCert, "RS256");
此外,我不会尝试使用来自 DPAPI 的密钥作为签名密钥,因为这些密钥不适合用于签名令牌。对于令牌签名,您需要 RSA 或 ECDSA 密钥,最简单的方法是将它们存储在 Azure Key Vault 中。您应该在应用程序外部配置和存储 DPAPI,但这仅用于保护会话 cookie。不签署令牌。
我非常怀疑您能否使用数据保护来为您管理和轮换签名密钥。 DPAPI 颁发并存储在密钥环中的密钥是对称的,而用于密钥签名的密钥需要是非对称的(public/private RSA/ECDSA 密钥)。基本上不兼容。
我有一个基于 IS4 + Net Core 3.1 的 authentication/authorization 服务器。 由于此身份服务与一些新的以及一些非常旧的应用程序交互,它还会创建 2 个不同的身份验证 cookie 和令牌。 我们目前正在使用 DPAPI 来签署 cookie 和我们需要的其他一些敏感信息。
到目前为止,我们一直在使用证书作为 IS4 中的 SigningCredential,但现在我希望能够使用 DPAPI 以便自动管理密钥轮换,或者至少,我们可以在一个一个地方。
基于IS4 docs我只需要实现ISigningCredentialStore
和IValidationKeysStore
,但是我不太熟悉这是如何管理的。
我有这样的近似值(我知道,此时它几乎毫无价值):
private class CustomSigningCredentialStore : ISigningCredentialStore
{
private readonly IKeyManager _keyManager;
public CustomSigningCredentialStore(IKeyManager keyManager) =>
_keyManager = keyManager;
public Task<SigningCredentials> GetSigningCredentialsAsync()
{
// For the sake of simplicity, lets assume
// that this is the correct one
var currentKey = _keyManager.GetAllKeys().ElementAt(0);
// Complete
return new SigningCredentials(...);
}
}
private class CustomValidationKeysStore : IValidationKeysStore
{
private readonly IKeyManager _keyManager;
public CustomValidationKeysStore(IKeyManager keyManager) =>
_keyManager = keyManager;
public Task<IEnumerable<SecurityKeyInfo>> GetValidationKeysAsync()
{
var keys = _keyManager.GetAllKeys();
// Complete
return keys.Select(key => new SecurityKeyInfo(...));
}
}
老实说,我被这个问题困住了,我不知道如何映射由 DPAPI 生成的当前密钥,它看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<key id="32f6d43e-97a9-4c4b-b108-e11f65e05cc4" version="1">
<creationDate>2020-07-31T00:00:00.0886417Z</creationDate>
<activationDate>2020-07-31T00:00:00.086065Z</activationDate>
<expirationDate>2020-08-30T00:00:00.086065Z</expirationDate>
<descriptor deserializerType="Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=3.1.8.0, Culture=neutral, PublicKeyToken=adb9793829ddae60">
<descriptor>
<encryption algorithm="AES_256_CBC" />
<validation algorithm="HMACSHA256" />
<masterKey p4:requiresEncryption="true" xmlns:p4="http://schemas.asp.net/2015/03/dataProtection">
<value>h1/a9G8i78kpnHBTEsisA5rk5ppm8vzByquAT2CO1OFnYHCX/eT/yfcFM/JigYkSDj+dupBz9ZZ7/XFMu/uWxg==</value>
</masterKey>
</descriptor>
</descriptor>
</key>
任何见解将不胜感激。
我最近实现了自己的 key-ring 存储,将密钥存储在 Azure Key Vault 中,我在此处发布了相关博客:
Storing the ASP.NET Core Data Protection Key Ring in Azure Key Vault
对于您询问的令牌登录,我首先从 Azure Key Vault 加载它们,然后将其手动添加到 IdentitySever,就像这样(使用一些自定义扩展方法):
// First we load the certificates (that contains the private keys) from Azure Key Vault
var rsaCert = KeyVaultExtensions.LoadCertificate(config, "rsa");
//Add RS256 (RSASSA-PKCS1-v1_5 using SHA-256)
builder.AddSigningCredential(rsaCert, "RS256");
此外,我不会尝试使用来自 DPAPI 的密钥作为签名密钥,因为这些密钥不适合用于签名令牌。对于令牌签名,您需要 RSA 或 ECDSA 密钥,最简单的方法是将它们存储在 Azure Key Vault 中。您应该在应用程序外部配置和存储 DPAPI,但这仅用于保护会话 cookie。不签署令牌。
我非常怀疑您能否使用数据保护来为您管理和轮换签名密钥。 DPAPI 颁发并存储在密钥环中的密钥是对称的,而用于密钥签名的密钥需要是非对称的(public/private RSA/ECDSA 密钥)。基本上不兼容。