I have a service fabric application where I am trying to call API with certificate based authentication.
WebRequestHandler handler = new WebRequestHandler();
//fetching certificate from key vault. The fetch url is identical in both the cases and thumbprint is same
X509Certificate certificate = GetCertificate();
handler.ClientCertificates.Add(certificate);
var baseUrl = "https://myUrl";
var requestUri = "request";
var content = "content";
using (HttpClient httpClient = new HttpClient(handler))
{
httpClient.BaseAddress = new Uri(baseUrl);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUri)
{
Content = new StringContent(content, Encoding.UTF8, MediaTypeNames.Text.Plain)
};
HttpResponseMessage result;
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(100)))
{
try
{
result = httpClient.SendAsync(request, cts.Token).Result;
//check the result here
}
catch (OperationCanceledException e) when (cts.IsCancellationRequested)
{
...
}
}
}
When I run the exact same code in local, it works and when I run it in Azure service fabric, it fails. Below is the result I am checking in code.
Service Fabric local cluster:
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: { Pragma: no-cache Cache-Control: no-cache Date: Sat, 06 Jun 2020 03:40:44 GMT Server: Microsoft-IIS/10.0 X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Content-Length: 67 Content-Type: application/json; charset=utf-8 Expires: -1 }
Service Fabric cluster in Azure:
StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: { Pragma: no-cache Cache-Control: no-cache Date: Sat, 06 Jun 2020 03:30:33 GMT Server: Microsoft-IIS/10.0 WWW-Authenticate: Bearer X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Content-Length: 61 Content-Type: application/json; charset=utf-8 Expires: -1 }
I checked WWW-Authenticate header is authentication server accepts. I know the it accepts Certificate based authentication and is working from local. Why is it denying authorization and sending back WWW-Authenticate: Bearer header when I run it in cloud?
I figured out that the certificate needs to have private key to Authorize and the key vault certificate I was using did not have private key.
It was bit confusing because certificate.HasPrivateKey was false in both my machine and azure environment. The reason it was working in my machine is that I had certificate installed in my machine.
I tested by deleting certificate from my store and resolved it by updating key vault with certificate that has private key.