I have configured an Azure website (with one ApiController) to use client-certificate authentication using the instructions provided here. Summarizing: you set the clientCertEnabled
flag to true
and from then on your website starts asking for a client-authentication-certificate.
Works great, however, now I want to access the client certificate that is sent to the server. According to the MSDN article, it should be available in the X-ARR-ClientCert
request header, except that it isn't!!
This means that anyone with a client-authentication-certificate can access my API, which is undesirable in my case.
So how do I retrieve the client-authentication-certificate that a client sends to my Web API?
UPDATE 1: I'm actually calling my API through Azure API Management. I configured APIM with my client-authentication-certificate and APIM calls my API without issues. However, when the API is called from APIM, no X-ARR-ClientCert header is set. When called directly via Fiddler, I do see the header. So APIM is calling my API in some different way?!?
UPDATE 2: I went through everything again and produced some logging. First the relevant part of the DelegatingHandler
class I'm logging from:
protected override async Task<HttpResponseMessage>
SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Trace.TraceInformation("Going to validate client certificate.");
var x509Certificate2 = request.GetClientCertificate();
Trace.TraceInformation("Client cert: {0}", x509Certificate2 == null
? "<null>"
: x509Certificate2.Subject);
try
{
var headerKeys = string.Join("|", request.Headers.Select(h => h.Key));
Trace.TraceInformation("Header keys: {0}", headerKeys);
...
And the resulting log output:
2015-12-07T08:08:24 PID[8464] Information Going to validate client certificate.
2015-12-07T08:08:24 PID[8464] Information Client cert: <null>
2015-12-07T08:08:24 PID[8464] Information Header keys:
Connection|Host|Max-Forwards|Conf-Organisation-Key|Ocp-Apim-Subscription-Key|
X-Forwarded-For|X-LiveUpgrade|X-ARR-LOG-ID|DISGUISED-HOST|X-SITE-DEPLOYMENT-ID|
X-Original-URL
So there's no client certificate and also no X-ARR-ClientCert
header.
UPDATE 3: And here's the log that results when I go to my actual API directly with a client-authentication-certificate:
2015-12-07T09:16:45 PID[8464] Information Going to validate client certificate.
2015-12-07T09:16:45 PID[8464] Information Client cert: [email protected]
2015-12-07T09:16:45 PID[8464] Information Header keys:
Connection|Accept|Accept-Encoding|Accept-Language|Cookie|Host|Max-Forwards|
User-Agent|Upgrade-Insecure-Requests|DNT|X-LiveUpgrade|X-ARR-LOG-ID|DISGUISED-HOST|
X-SITE-DEPLOYMENT-ID|X-Original-URL|X-Forwarded-For|X-ARR-SSL|X-ARR-ClientCert
Both a client certificate directly from the request and the expected X-ARR-ClientCert
header.
UPDATE 4: In the end this happened to be my own mistake (of course). I was convinced that the url for the backend was https
while in fact it was http
. Client certificate authentication only works over https so in hindsight it made perfect sense no certificate was found in the backend...