1
votes

I've seen both this and this — same problem, different question.

I'm trying to connect my Windows 8.1 Store app to an ASP.NET Web API web service, secured over HTTPS using a self-signed certificate. It's a proof-of-concept application that will end up on < 5 different machines and seen only internally, so I was planning to just install the certificate as trusted on each of the target machines.

When I try this on my development setup, both HttpClient APIs fail to establish the trust relationship when calling the service.

  • Windows.Web.Http.HttpClient exception: "The certificate authority is invalid or incorrect"
  • System.Net.Http.HttpClient exception: "The remote certificate is invalid according to the validation procedure."

My self-signed certificate (public-key-only .cer version) is installed in both the "User" and "Local Machine" Trusted Root Certification Authorities on the client. I'm really surprised that this isn't enough to get WinRT to trust it. Is there something I'm missing, or is there just no way to set up the trust relationship for a self-signed SSL certificate that will make HttpClient happy?

Details on my setup:

  • ASP.NET Web API
  • Azure web role running in Azure emulator
  • Cert issuer: 127.0.0.1
  • Cert subject: 127.0.0.1
  • Cert key: 2048-bit
  • Windows 8.1 Store application
  • Certificate (.cer file with public key only) installed in User\Trusted Root Certification Authorities
  • Certificate (.cer file with public key only) installed in Local Machine\Trusted Root Certification Authorities
  • Certificate (.cer file with public key only) added to Windows Store app manifest under "CA"

I am not asking for a workaround to configure HttpClient to accept self-signed or invalid certificates in general — I just want to configure a trust relationship with THIS one. Is this possible?

2

2 Answers

2
votes

You should be able to find out what is the problem with the certificate by doing a request like this:

// using Windows.Web.Http;

private async void Foo()
{
    HttpRequestMessage request = null;
    try
    {
        request = new HttpRequestMessage(
            HttpMethod.Get,
            new Uri("https://localhost"));

        HttpClient client = new HttpClient();
        HttpResponseMessage response = await client.SendRequestAsync(request);
    }
    catch (Exception ex)
    {
        // Something like: 'Untrusted, InvalidName, RevocationFailure'
        Debug.WriteLine(String.Join(
            ", ",
            request.TransportInformation.ServerCertificateErrors));
    }
}

Using a HttpBaseProtocolFilter you can ignore certificate errors:

// using Windows.Web.Http;
// using Windows.Web.Http.Filters;
// using Windows.Security.Cryptography.Certificates;;

HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationFailure);
HttpClient client = new HttpClient(filter);

HttpResponseMessage response = await client.SendRequestAsync(request);
1
votes

The piece I was missing turned out to be that the certificate wasn't in the list of of IIS Server Certificates on my local machine!

Opening IIS Manager and checking out the Server Certificates section, I did find a 127.0.0.1 SSL certificate already set up by the Azure emulator:

  • CN = 127.0.0.1
  • O = TESTING ONLY
  • OU = Windows Azure DevFabric

However, my own self-signed certificate that I made outside of IIS, also with CN=127.0.0.1, was not in the list. I imported it, and now my Windows Store app's HttpClient connects happily (certificate warnings went away in Chrome and IE as well!)

If anyone can firm up the technical details on this, please comment — this fix feels a bit magical and I'm not sure I can pinpoint precisely why this worked. Possibly some confusion on my part between the two certs for 127.0.0.1, even though the thumbprint I had configured in my Azure project was always the one I was intending to use?