this one has kept me busy for the past day.
I'm trying to use Azure Key Vaults service from my .net core 2.2 app using a certification as security.
I'm installing the certificate within the same code on the startup of an application, using a base64 encoded string as input parameter.
When installing in the StoreLocation.LocalMachine
(and running VS as admin) the application works fine and the secrets are retrieved.
When using StoreLocation.CurrentUser
, the application throws a NullReferenceException
when trying to retrieve the secrets from the vault.
at Microsoft.IdentityModel.Clients.ActiveDirectory.CryptographyHelper.SignWithCertificate(String message, X509Certificate2 certificate)
at Microsoft.IdentityModel.Clients.ActiveDirectory.JsonWebToken.Sign(IClientAssertionCertificate credential)
at Microsoft.IdentityModel.Clients.ActiveDirectory.ClientKey.AddToParameters(IDictionary`2 parameters)
at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.<SendTokenRequestAsync>d__64.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.IdentityModel.Clients.ActiveDirectory.AcquireTokenHandlerBase.<RunAsync>d__55.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext
....
I've seen people mentioning the same kind of exception back in 2017 when moving to .NET 4.7 (Here and Here).
I tried to run the application with various newer versions of the Microsoft.IdentityModel.Clients.ActiveDirectory
package without success. From 3.14 to 3.19 it throws the same exception. From 4.3 onwards it's missing the .Platforms
dll which is no longer provided by the package.
Finally, I fetched, compiled and ran the examples application from the Extensions repository (which is also using CurrentUser
location and I have the same exception.
I have not yet tried to run it on .NET Core 3.0. But I believe something is wrong with the initial writing.
I'm running out of further resources to investigate so I'm reaching out to the community :)
Below is the code as a simple sample app that I use to write/read the certificate.
dotnet .\Certificates.dll -- -c {cert-base64-encoded-string} -p {cert-password}
public static Main(string[] args)
{
//// Using CommandLineParser
var options = Parser.Default.ParseArguments<Options>(args)
.WithParsed(o =>
{
if (!string.IsNullOrEmpty(o.Certificate))
{
o.CertPassword = o.CertPassword ?? throw new ArgumentNullException("No certificate password provided.");
var rawData = Convert.FromBase64String(o.Certificate);
//// install certificate
using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser, OpenFlags.ReadWrite))
{
var cert = new X509Certificate2(rawData, o.CertPassword, X509KeyStorageFlags.PersistKeySet);
ThumbPrint = cert.Thumbprint;
store.Add(cert);
}
}
});
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(configHost =>
{
using (var store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(X509FindType.FindByThumbprint, ThumbPrint, false);
configHost.AddAzureKeyVault(_vault, _key, certs.OfType<X509Certificate2>().Single());
}
})
.UseStartup<Startup>();
While I was writing up the GitHub readme file for this problem's example, I stumbled upon the solution.
It pains me to say that it was a human error...
I was passing in a wrong Base64String for the certificate. Probably one that I created earlier.
When passing in the correct generated string in the command, the code started working. You can see it on my GitHub
In short it was failing because the certificate I used on the client did not correspond with the one on the server. Though the exception could be clearer.