I have an authentication/authorization server based on IS4 + Net Core 3.1. Since this Identity Service interacts with some new as well as some quite legacy applications, it also creates 2 different authentication cookies plus tokens. We are are currently using DPAPI to sign cookies and some other sensitive information we need.
So far, we've been using a certificate as a SigningCredential in IS4, but now I want to be able to use DPAPI so that key rotation is managed automatically, or at least, we can manage them all in a single place.
Based on IS4 docs I just need to implement ISigningCredentialStore
and IValidationKeysStore
, however I am not quite familiar with how this is managed.
I've got an approximation like this (I know, it is almost worhtless at this point):
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(...));
}
}
I am stuck with this to be honest, I don't know how to map current keys generated by DPAPI, which looks like this:
<?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>
Any insight will be extremelly appreciated.
I recently implemented my own key-ring store that stores the keys in Azure Key Vault and I blogged about that here:
Storing the ASP.NET Core Data Protection Key Ring in Azure Key Vault
For token signin that you ask about, I first load them from Azure Key Vault and then add it manually to IdentitySever, like this (using some custom extension methods):
Also, I wouldn't try to use the keys form DPAPI as signing keys, because those keys are not suitable for singing tokens. For token signing you want RSA or ECDSA keys and the simplest is to store them in Azure Key Vault for example. DPAPI you should configure and store outside your application, but that is only used for protecting the session cookies. Not signing tokens.
I highly doubt you can use the data protection to manage and rotate the signing keys for you. The keys issued by DPAPI and stored in the key ring are symmetrical while the keys for key signing needs to be asymmetrical (public/private RSA/ECDSA keys). Basically, they are not compatible.