NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802 in iOS10, 2017

Josh picture Josh · Jan 25, 2017 · Viewed 7.8k times · Source

THIS IS NOT A REPEATED QUESTION, READ ON. I am upgrading the deprecated code in my app to iOS10 compliance.

THE ERROR: NSURLSession is giving me trouble, with this infamous error, along with 9806 and 9801, depending on what I put on the .plist file:

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

MY CODE: In my Info.plist file, I have:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>https://my.own-server.com</key>
            <dict>
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSExceptionAllowInsecureHTTPSLoads</key>
                <true/>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <true/>
                <key>NSExceptionMinimumTLSVersion</key>
                <string>TLSv1.0</string>
                <key>NSThirdPartyExceptionAllowInsecureHTTPSLoads</key>
                <false/>
                <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSThirdPartyExceptionMinimumTLSVersion</key>
                <string>TLSv1.0</string>
                <key>NSRequiresCertificateTransparency</key>
                <false/>
            </dict>
        </dict>
        <key>NSAppTransportSecurity</key>
        <dict>
            <key>NSAllowsArbitraryLoads</key>
            <false/>
        </dict>
    </dict>

In my ObjectiveC code, I have this:

NSURLSessionConfiguration *defaultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session __unused = [NSURLSession sessionWithConfiguration:defaultConfiguration delegate:[PortalRequest alloc] delegateQueue:[NSOperationQueue mainQueue]]; operationQueue:[NSOperationQueue mainQueue]];
    requestContainer.sessionDataTask = [session dataTaskWithRequest:request];
[self.sessionDataTask resume];

In the DELEGATE method of the class where make the URLSession call, I can see didReceiveChallenge:

LOG: ** NSURLSession IOS10 ** - didReceiveChallenge called

...and finally I get the error:

[TIMESTAMP] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9806)

THE SERVER None of the solutions proposed in other answers work, is it because of Apple's 2017 deadline? https://techcrunch.com/2016/06/14/apple-will-require-https-connections-for-ios-apps-by-the-end-of-2016/ According to this online security analysis tool, https://www.ssllabs.com/ssltest/analyze.html The backend DOES support TLS 1.2

Any ideas on how to solve this?? Do you know where to find some iOS sample code to be 100% sure the endpoint I am pointing at is guilt free?

UPDATE This code works for me, any opinions on it?:

- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler{
    NSLog(@"*** KBRequest.NSURLSessionDelegate - didReceiveChallenge IOS10");

    if([challenge.protectionSpace.authenticationMethod
        isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        if([challenge.protectionSpace.host
            isEqualToString:@"engine.hello-indigo.com"])
        {
            NSURLCredential *credential =
            [NSURLCredential credentialForTrust:
             challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
        }
        else
            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
    }
}

Answer

Idali picture Idali · Jan 25, 2017

Try to set NSExceptionRequiresForwardSecrecy to false. However your server do meet the min requirement for Transport Layer Security (TLS) protocol version, your server Connection-Cipher may not support forward secrecy.

The negotiated Transport Layer Security (TLS) version must be TLS 1.2. Attempts to connect without TLS/SSL protection, or with an older version of TLS/SSL, are denied by default.

The connection must use either the AES-128 or AES-256 symmetric cipher.

The negotiated TLS connection cipher suite must support perfect forward secrecy (PFS) through Elliptic Curve Diffie-Hellman Ephemeral (ECDHE) key exchange, and must be one of the following:

TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA