ClientCertificates and WebException: The request was aborted: Could not create SSL/TLS secure channel.

If you are using X509 ClientCertificates with a webservice client called from IIS and the service endpoint uses the HTTPS protocol (SSL) the following exception can occur: WebException: The request was aborted: Could not create SSL/TLS secure channel.
System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel. at System.Web.Services.Protocols. WebClientProtocol.GetWebResponse(WebRequest request) at System.Web.Services.Protocols. HttpWebClientProtocol.GetWebResponse(WebRequest request) at System.Web.Services.Protocols. SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
The curious part is that everything works great while running unittests on the service directly; it's IIS that throws a wrench in it. To add some more grief to the equation this particular scenario played out in a test environment with self-signed certificates. So my initial investigation concentrated on making sure the root certificate was in the right place (LocalMachine\My and Root). All seemed well, but the exception persisted. I resorted to disabling certificate verification, still the exception persisted. Finally Microsoft KB article 901183 'How to call a Web service by using a client certificate for authentication in an ASP.NET Web application' put me on the right track:
Step 2: Configure access to the client certificate In this step, you must grant permission for the ASP.NET account to access the client certificate that is stored in the local machine store. The Network Service account is the default account for running Web applications on Windows Server 2003. Therefore, you must grant access to the certificate for the Network Service account. If you have configured a custom account to run ASP.NET, you must grant access for the custom account. Note In Microsoft Internet Information Server (IIS) 5.0, ASP.NET runs under the ASPNET account and not under the Network Service account. Therefore, you must to grant permissions for the ASPNET account on a computer that is running IIS 5.0. To grant access for a specific user account, run the following command at a command prompt: WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s "IssuedToName" -a "AccountName"
And voila! My service client happily zoomed along again. Why did it work while unittesting and not in IIS? The certificate was installed under the developer account, which grants the necessary permissions to the private key for that account immediately, but the NetworkService account was lacking them which caused the underlying connection to be closed... Microsoft has included the tool FindPrivateKey in the Windows Communication Foundation (WCF), Windows Workflow Foundation (WF) and Windows CardSpace Samples which can help you locate the private key file and check (and change) its permissions. I hope it helps some of you out there struggling with the same issue!

3 comments:

  1. This saved my day today! I granted permission to quite a few Users before hitting on this page and granting to NETWORKSERVICE. Solved my problem, thanks!

    ReplyDelete
  2. Thanks, this was very helpful. In my case, I was having difficulties doing an XML-RPC call to a third-party site using client certificates. My IIS6 server wasn't being able to load the certs, it only did when the IIS app user was logged on.
    Finally I decided to install those certs in the LocalComputer store as well, and made my code inspect both the CurrentUser and LocalComputer stores.
    Lastly, it was imperative to have those certs copied onto the local drive. (installing them from a remote server wouldn't do the job).

    Hope this helps someone else. I spent about 3 days on this.

    ReplyDelete
    Replies
    1. You're welcome! Good to hear that helped you.
      Thanks for sharing your findings as well!

      Delete

My Latest Track