Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Server Authentication in Swift 2.0 & XCode 7 broken

I just updated my code to Swift 2.0 to work with Xcode 7. My App performs NSURLAuthenticationMethodServerTrust and NSURLAuthenticationMethodClientCertificate authentication.

The problem is NSURLAuthenticationMethodServerTrust authentication stopped working on my simulator - but still works on my test device with iOS 8.3. Besides my old project which is not Swift 2.0, is also still working.

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

Error retrieved from NSURLSession:

Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo=0x7fcf75053070 {NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x7fcf73700d00>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorCodeKey=-9802, NSUnderlyingError=0x7fcf735284b0 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1200.)", NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://mywebapi/dosomething, NSErrorFailingURLStringKey=https://mywebapi/dosomething, _kCFStreamErrorDomainKey=3} [GetOneTimeTokenController.swift:76]

I am still targeting iOS 8.0 for deployment.

This is how I handle the Authentication Challenge (using a self signed certificate):

if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {

        let urlCredential:NSURLCredential = NSURLCredential(
            identity: identityAndTrust.identityRef,
            certificates: identityAndTrust.certArray as [AnyObject],
            persistence: NSURLCredentialPersistence.ForSession);

        completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, urlCredential);

    } else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {

        completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, NSURLCredential(trust: challenge.protectionSpace.serverTrust!));

    } else {

        challenge.sender?.continueWithoutCredentialForAuthenticationChallenge(challenge)
        Logger.sharedInstance.logMessage("Unexpected Authentication Challange", .Error);

    }
like image 623
Bins Ich Avatar asked Jun 18 '15 09:06

Bins Ich


1 Answers

Your simulator is most likely running iOS 9 then. In iOS 9, TLS 1.2 is enforced. If you're not using it, your requests will fail.

Check out this post for more info.

You can bypass it by putting this in your Info.plist:

<key>NSAppTransportSecurity</key>
<dict>
  <!--Include to allow all connections (DANGER)-->
  <key>NSAllowsArbitraryLoads</key>
      <true/>
</dict>

but it is simply a temporary workaround until you can implement TLS 1.2.

like image 149
vrwim Avatar answered Sep 30 '22 14:09

vrwim