25

I am getting following error with self signed certificate

Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made.

while testing web-services for one of my demo app with

Note: before assuming its Duplicate, I would request please read it all the way,even same i have reported to apple dev forums

Using Alamofire Library


func testAlamofireGETRequest() -> Void
    {
        Alamofire.request(.GET, "https://filename.hostname.net/HelloWeb/service/greeting/john")
            .responseJSON
        { response in
            print("Response JSON: \(response.result.value)")
        }
}

Using NSURLSession


func testNSURLSessionRequest() -> Void {

        let session = NSURLSession.sharedSession()
        let urlString = "https://filename.hostname.net/HelloWeb/service/greeting/john"
        let url = NSURL(string: urlString)
        let request = NSURLRequest(URL: url!)
        let dataTask = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
            print("done, error: \(error)")

            //Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made.
        }
        dataTask.resume()
    }

I spent 2 days with no luck :(

there are bunch of questions already posted but nothing worked for me

posted Alamofire git issue


My Info.pist file is updated for ATS settings this way

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>filename.hostname.net</key>
            <dict>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                <true/>
            </dict>
        </dict>
    </dict>

Meanwhile I am able to get response for

http://filename.hostname.net

and https://google.com

but not for https://filename.hostname.net

Can anyone please suggest me why I am not able to get this working after huge efforts?

Community
  • 1
  • 1
swiftBoy
  • 35,607
  • 26
  • 136
  • 135
  • How about starting with looking at the SSL handshake? Can you use Wireshark? – Greycon Mar 31 '16 at 11:09
  • RDC, It worked for me: The response for I got is: `SUCCESS:

    Auth Key Missing!

    ` which is perfect, I didn't supply headers to my server. It is working on my side. check gist: https://gist.github.com/tush4r/142ba2a45bc9ed538dbe393be7ce36e2
    – tush4r Mar 31 '16 at 14:29

4 Answers4

53

At the command-line in OS X, run the following:

nscurl --ats-diagnostics https://filename.hostname.net --verbose

This will tell you what combinations of ATS settings will and will not permit iOS to access your site, and should point you towards what is wrong with your site.

It could be one or more of the following

  • Certificate hash algorithm (must be SHA-256 or above)
  • TLS version (must be 1.2)
  • TLS algorithms (must provide Perfect Forward Secrecy)
swiftBoy
  • 35,607
  • 26
  • 136
  • 135
yaakov
  • 5,552
  • 35
  • 48
  • 1
    As mentioned by @Codran, I had exactly same response and got it bypassed by the method mentioned. RDC, I will re-create your situation on a local server and then let you know. – tush4r Mar 31 '16 at 12:30
  • 2
    @codran, For me above command showing "Result: PASS" for every case & also I have added ATS settings in my info.plist, But, still at times I see SSL related issues on crashytics. Any thoughts? – JiteshW Dec 13 '16 at 09:42
  • @JiteshW exactly my case. Nothing, outside allowing insecure loads altogether, works – Antek Feb 14 '18 at 16:07
9

Apple has released the full requirements list for the App Transport Security.

Turned out that we were working with TLS v1.2 but were missing some of the other requirements.

Here's the full check list:

  • TLS requires at least version 1.2.
  • Connection ciphers are limited to those that provide forward secrecy (see below for the list of ciphers.)
  • The service requires a certificate using at least a SHA256 fingerprint with either a 2048 bit or greater RSA key, or a 256bit or greater Elliptic-Curve (ECC) key.
  • Invalid certificates result in a hard failure and no connection.
  • The accepted ciphers are: 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
Cœur
  • 37,241
  • 25
  • 195
  • 267
TechnicalTophat
  • 1,655
  • 1
  • 15
  • 37
  • @Cœur Here it is: [Link](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW57) – zvi Mar 22 '17 at 11:53
5

I presume the server you are trying to connect has invalid certificates or doesn't match up with the iOS 9 standards for ECC, Ciphers etc.

  • If you’re using high-level networking APIs—NSURLSession, NSURLConnection, or anything layered on top of those—you don’t have direct control over the cypher suites offered by the client. Those APIs choose a set of cypher suites using their own internal logic.

  • If you’re using lower-level networking APIs—CFSocketStream, via its NSStream and CFStream APIs, and anything lower than that—you can explicitly choose the set of cypher suites you want to use. How you do this depends on the specific API.

The standard practice is:

  1. create the stream pair

  2. configure it for TLS

  3. get the Secure Transport context using the kCFStreamPropertySSLContext property

  4. configure specific properties in that context

  5. open the streams

You can see an example of this in the TLSTool sample code. Specifically, look at the TLSToolServer class, where you can see exactly this sequence.

In a very short context, you want to configure the stream in such a way that it bypasses the security, however, in the case of Alamofire you can do this directly by:

func bypassAuthentication() {
        let manager = Alamofire.Manager.sharedInstance
        manager.delegate.sessionDidReceiveChallenge = { session, challenge in
            var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
            var credential: NSURLCredential?
            if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
                disposition = NSURLSessionAuthChallengeDisposition.UseCredential
                credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
            } else {
                if challenge.previousFailureCount > 0 {
                    disposition = .CancelAuthenticationChallenge
                } else {
                    credential = manager.session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)
                    if credential != nil {
                        disposition = .UseCredential
                    }
                }
            }
            return (disposition, credential)
        }
    }

let me know if that helps. Thank you!

tush4r
  • 867
  • 12
  • 21
  • If this doesn't, let me know - I will help you configure the stream properly by disabling the ECDHE TLS cypher suites. – tush4r Mar 31 '16 at 11:33
  • Unfortunately this did not help me :( I have updated the question post as well. – swiftBoy Mar 31 '16 at 12:06
  • Why is this the chosen answer @swiftBoy? Did you get it to work in the end? – SuperHanz98 Aug 13 '19 at 08:47
  • @Cutter this solution helps you in bypassing the TLS/SSL requirements so that you can continue with the development. It isn't much you can do to fix it from the iOS, as the SSL is configured on the server, which ideally should be higher or equal to minimum TLS version. – tush4r Aug 13 '19 at 10:32
5

I had same scenario and got stuck for a day. Try with your mobile data, if this works fine with your API, then problem with your network firewall. then enable SSL / TLS from firewall settings.

Hasya
  • 9,792
  • 4
  • 31
  • 46