0

I am writing an iOS app that hits one of our own web servers to leverage data. The IIS web server is publicly-accessible, has valid cryptography certificates, and uses TLS 1.2. To my knowledge, all that is up to snuff with App Transport Security. When making web requests in the app, the request times out, but more interestingly, this message is logged "NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9806)".

This IIS server happens to Accept X509 client certificates for a separate use case that does not involve the mobile app. Changing the setting to Ignore results in the iOS app hitting the server fine. I assume the timeout occurs because the server is prompting the app for a client certificate and it doesn't just respond that it doesn't have one. Note, I don't have the client certificates set to Require. I am not sure how to have the iOS app play nicely and just carry on when prompted by the server for a client certificate.

Is there a way to get this to work in iOS while allowing the IIS server to still Accept client certificates? I don't want to diminish ATS by adding hacky exclusions to info.plist.

I don't think it's relevant, but I am developing the iOS app in Xamarin.IOS in C#. A request goes something like this:

 using (var client = new WebClient()) { client.Headers.Add(Constants.RequestHeaders.RequestId, nonce.RequestId.ToString()); client.Headers.Add(Constants.RequestHeaders.Signature, Convert.ToBase64String(nonce.DigitalSignature)); client.Headers.Add(HttpRequestHeader.ContentType, "application/json"); var resultJson = client.UploadString("https://foo.com/Api/Register", json); } 

EDIT:

I was able to resolve this issue by using the library ModernHttpClient available via NuGet. The API site accepts client certificates, but does not require them. In most browsers, this results in a one-time prompt by the browser asking you to specify the cert you'd like to use. However, in iOS, making a programmatic web request by default does not bring up a prompt (of course) nor does it inform the server it does not have a cert to provide. Hence, the request simply timed out. With ModernHttpClient, I found a way to set this behavior to automatically resolve.

 var handler = new NativeMessageHandler(); handler.ClientCertificateOptions = ClientCertificateOption.Automatic; using (var client = new HttpClient(handler)) { ... 

Now it works fine. I'd prefer to not have to include a library just for this very specific purpose, but it works. Perhaps this specific functionality could be distilled into a few lines of code without using the library? Regardless, I'm thankful for ModernHttpClient solving this issue; it's really hacky to change server behavior just to support an iOS quirk.

1 Answer 1

1

Can you try change iOS Build setting.

  1. change SSL/TLS implement use * Apple TLS *
  2. change HttpClient implementation use * NSUrlSession *

I had similar problem and using HttpClient to call our public Https API, above setting fixed the issue.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.