I'm trying to set up client certificate authentication to an external API. The non-exportable client certificate is in Azure Key Vault. My code is C# (.NET Core) in an Azure v2 Function hosted in an app service plan. Because the client certificate is non-exportable, I can't drop it into my app service plan's certificate store.
I have previously got a client certificate authentication PoC working with an exportable client certificate from Azure Key Vault. I've imported the exportable client certificate into my app service plan's certificate store, and from there I'm just using HttpClient and HttpClientHandler in a pretty standard way:
builder.Services.AddHttpClient("certificateClient")
.ConfigurePrimaryHttpMessageHandler(
() => {
var handler = new HttpClientHandler();
handler.SslProtocols = SslProtocols.None;
handler.ClientCertificates.Add(certificate);
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
return handler;
});
builder.Services.AddScoped<HttpClient>(i => i.GetRequiredService<IHttpClientFactory>().CreateClient("certificateClient"));
The certificate is retrieved from the app service plan's key store. This works. I just attach the client certificate to the HttpClientHandler and all the client certificate authentication handshake is handled automatically by the underlying Azure Functions/ASP.NET Core infrastructure.
Now that I have a non-exportable client certificate which is not in my app service plan's key store, I can't attach it to my HttpClient's HttpClientHandler, so the above won't work.
As I understand it, the private key signing of the "proof" data required in the TLS client authentication handshake will need to be delegated to the Azure Key Vault's encryption facilities. I'm trying to find out how to get this delegated private key signing working at an infrastructural level where it belongs, through a call to something like HttpClient or HttpClientHandler.
I can't find any methods/properties in the API docs for HttpClient(Handler) or ASP.NET Core which can do this at an infrastructural level. They might exist, I just can't find them.
I don't have sample code because I can't figure out which APIs to use, or if this is even possible in my C# v2 functions tech stack. Is there some other ASP.NET Core class which handles this sort of problem? Am I trying to go about this in the wrong way? i.e. do I need to stop trying to stay with HttpClient(Handler) and try a radically different way of doing this?
NOTE: I don't think it's sensible to try and re-implement the TLS client authentication handshake in application code before exhausting all other options. While attaching the public client certificate in a header is easy, I think it will be very difficult to do the generation of the "proof" data needed for private key signing myself. I don't think I'll easily get access to the right data to generate the "proof" data that will match what the server side TLS stack also generates. I'd also much rather delegate this to infrastructure, so handling it in application code is my absolute action of last resort.