I have a self-hosted WCF REST service based on the WebHttpBinding. One of the methods on the service looks something like this:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "myMethod")]
Stream MyMethod(Stream contents);
I wrote a simple test program that creates a HttpWebRequest to try and POST data to this method. This works fine in the following scenarios:
- Service is not using any security.
- Service is using transport security without client certificate.
- Service is using transport security with client certificate and I POST 0 bytes.
If I try to use transport security with a client certificate a POST more than 0 bytes, the service returns HTTP 403 (forbidden), and it never hits any of my code.
This is driving me nuts.
Any ideas?
UPDATE
After enabling tracing for http.sys, I observed the following message in the trace:
Attempt by server application to receive client certificate failed with status: 0xC0000225.
Does anyone know what this means? I’m certain that I’m sending the client certificate and certain that it’s trusted by the host machine.
After long and painful searching, I finally discovered that the problem was a corrupt client certificate. Although there were no outward indications, the private key for this certificate was not saved on the local machine. We generated the certificate in code, and then imported it into the current user’s personal store. We did not, however, set the RSACryptoServiceProvider.PersistKeyInCsp property on the object used to generate the private key. As a result, .NET deleted the private key container and the imported certificate ended up referencing a non-existant private key.
The response to this post goes over the gotchas in importing certificates with .NET in some detail: Inserting certificate with private key.