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 ).
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.