2

I am working on client certificate-based authentication with self-hosted web API but web API always return null when trying to get a certificate from the request using GetRequestContext().ClientCertificate

Here is code on web API side

    protected override System.Threading.Tasks.Task<HttpResponseMessage>
                SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
  HttpResponseMessage response = ValidateCertificate(request);
            if (response.StatusCode == HttpStatusCode.OK)
                return base.SendAsync(request, cancellationToken);
            else
                return Task<HttpResponseMessage>.Factory.StartNew(() => response);
        }

private HttpResponseMessage ValidateCertificate(HttpRequestMessage request)
        {
            var certificateFromRequest = request.GetRequestContext().ClientCertificate;

            if (certificateFromRequest == null)
            {
                return request.CreateResponse(HttpStatusCode.NotAcceptable, "Certificate is not available in request!");
            }

On Client side code is:

WebRequestHandler handler = new WebRequestHandler();
            X509Certificate2 certificate = ConfigurationManager.AppSettings["MSIClientCertificateThumbprint"].CleanThumbprint().GetCertByThumbprint();

            handler.ClientCertificates.Add(certificate);
using (var httpClient = new HttpClient(handler))
            {
                var response = await httpClient.PostAsync($"{ConfigurationManager.AppSettings["WEBAPIPATH"]}/api/controller/{param}", null);
                response.EnsureSuccessStatusCode();
            }

I always see certificate is being properly passed in the HTTPClient with private keys on it but still, web API fails to find it

vivek jain
  • 291
  • 3
  • 13

1 Answers1

0

Solve it by updating the client project to net461 from net452.

HttpClient requires the private key to be available on the certificate when adding a client certificate

I was generating a certificate from the following PowerShell command

New-SelfSignedCertificate -Subject "Subject" -FriendlyName "Name" -NotAfter (Get-Date).AddYears(5) -CertStoreLocation cert:\localmachine\my 

which generates a CNG crypto-based private key and that is not supported by net452

Also, I had to add additional arguments to PowerShell command to generate certificate after updating client project to net461

New-SelfSignedCertificate -Subject "UcClearly" -FriendlyName "UcClearly.MSI.API" -NotAfter (Get-Date).AddYears(5) -CertStoreLocation cert:\localmachine\my -KeyExportPolicy Exportable -KeySpec Signature
vivek jain
  • 291
  • 3
  • 13