I'm upgrading from identity server 4 to duende identity server 6.
When running locally I can reference a key up on Azure Key Vault no problems via "DefaultAzureCredential" and it sets it correctly.
BUT :(
Then the site runs (site and identity server all running as one) and I login it throws an exception "WindowsCryptographicException: Key does not exist"
var identityServiceBuild = services.AddIdentityServer(options =>
{
options.KeyManagement.Enabled = false;
});
string keyVaultName = "mykeyvault";
var kvUri = "https://" + keyVaultName + ".vault.azure.net";
var keyClient = new KeyClient(new Uri(kvUri), new DefaultAzureCredential());
var keyResponse = keyClient.GetKey("devidentityserver");
RSA rsa = keyResponse.Value.Key.ToRSA();
key = new RsaSecurityKey(rsa) { KeyId = keyResponse.Value.Properties.Version };
identityServiceBuild.AddSigningCredential(key, IdentityServerConstants.RsaSigningAlgorithm.RS256);
Here is more of the stack trace if that helps:
Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Key does not exist.
at Internal.Cryptography.CngCommon.SignHash(SafeNCryptKeyHandle keyHandle, ReadOnlySpan`1 hash, AsymmetricPaddingMode paddingMode, Void* pPaddingInfo, Int32 estimatedSize)
at System.Security.Cryptography.RSAImplementation.RSACng.SignHash(Byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider.Sign(Byte[] input)
at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.CreateEncodedSignature(String input, SigningCredentials signingCredentials)
at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.CreateTokenPrivate(JObject payload, SigningCredentials signingCredentials, EncryptingCredentials encryptingCredentials, String compressionAlgorithm, IDictionary`2 additionalHeaderClaims, String tokenType)
at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.CreateToken(String payload, SigningCredentials signingCredentials, IDictionary`2 additionalHeaderClaims)
at Duende.IdentityServer.Services.DefaultTokenCreationService.CreateJwtAsync(Token token, String payload, Dictionary`2 headerElements) in /_/src/IdentityServer/Services/Default/DefaultTokenCreationService.cs:line 138
Is it because it's expecting the key to be persisted as a row in the "Keys" SQL table? I'm thinking not because I've disabled key management via KeyManagement.Enabled = false?
Help!
The problem is that this line:
Only will return the public key from KeyVault, to get the private key, you need to get it as a secret. (yes, its odd).
This is the code I use in my setup to get the key from keyvault: