简体   繁体   中英

WebRequest client certificate null on WebAPI side

I have a WebApi controller action that I decorated with my [x509Authorize] attribute. I'm debugging this endpoint locally - and at the same time running a console application that tries to call this endpoint.

Client side

Here's the client code - slightly simplified:

X509Certificate Cert = X509Certificate.CreateFromCertFile("C:\\Temp\\ht-android-client.pfx");               
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://localhost:44300/api/mobile/predict");
Request.ClientCertificates.Add(Cert);
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
....

I've asserted that the Cert is the correct certificate. I've installed the .pfx in my CurrentUser\\Personal store and in the LocalMachine\\Personal store - and modified to take the Cert from that store, as suggested here but that doesn't seem to make a difference:

var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
var Cert = store.Certificates.Find(X509FindType.FindBySubjectName, "Android", true)[0];

Server side

And I'm listening on the WebAPI endpoint like with the following code:

public class x509AuthorizeAttribute : AuthorizeAttribute
{
    public override Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        var cert = actionContext.Request.GetClientCertificate();
       // value of 'cert' is null

I hit a breakpoint in the console app first - see that the correct certificate is selected. Then I hit the breakpoint on the server and see that the value of .GetClientCertificate() is null . What am I doing wrong? The other SO questions 1 and 2 didn't help me any further.

Additional information on the certificates

I've created a self-signed CA certificate which is installed on the LocalMachine\\Trusted root CA store. I've created the android client cert - and signed it with my self-signed CA certificate. Then I converted that into a pkcs12 file. This is the certificate that the client is using - which is also installed in my personal stores ( both machine and currentUser ) and is valid ( you can see the chain go back to the ROOT CA cert ).

Also - the certificate's purpose is set to clientAuth: 在此输入图像描述

So the problem is indeed that the server needs to have the following set in the web.config in order to force IIS to start the SSL cert negotiation:

<security>
    <access sslFlags="SslNegotiateCert" />
</security>

If this is not present - the certificate will be ignored and you will get null on the GetClientCertificate() call.

This implies however that all clients for my WebAPI are now forced to present a valid certificate - so my original idea of having just one controller method requiring a certificate does not seem possible.

Then there's the challenge of setting this config paramter in web.config, because of the restrictions for Azure Cloud Services. However - this answer provides a solution for that.

EDIT

On a side note this is not supported yet in ASP.NET vNext ( v rc-01-final )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM