Problems porting NSURLConnection code

We are updating a very old codebase (2010) that used Objective-C. Users of the app were able to enter in a base URL to either their own server solution, or our company's hosted solution. For the latter, users would typically enter in an http address and via redirects, were ultimately given a secure connection. Reason I added these details is that the URL the users enter is completely arbitrary and not just one fixed domain.


For networking, we used NSURLConnection and provided the following delegate implementations.


- (BOOL)connection:(NSURLConnection*)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace*)protectionSpace
{
  NSString* authenticationMethod = [protectionSpace authenticationMethod];

  return [authenticationMethod isEqualToString:NSURLAuthenticationMethodDefault] ||
  [authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic] ||
  [authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPDigest] ||
  [authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}


- (void)connection:(NSURLConnection*)conn didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge
{
    id<NSURLAuthenticationChallengeSender>  sender;
    sender = [challenge sender];

    NSURLProtectionSpace* protectionSpace = [challenge protectionSpace];
    SecTrustRef trust = [protectionSpace serverTrust];
    NSURLCredential* credential = [NSURLCredential credentialForTrust:trust];

    [sender useCredential:credential forAuthenticationChallenge:challenge];
}


But connection:canAuthenticateAgainstProtectionSpace: is deprecated. It's my understanding though from reading though docs that one would implement a session-level challenge API. Then for the other piece, a task-level challenge API. Here is our basic Swift (4.2) code (this code is in a view controller which is a URLSessionTaskDelegate:


  let theURL = ...
  let theConfiguration = URLSessionConfiguration.default

  theConfiguration.httpAdditionalHeaders = ["Accept" : "application/json"]

  let theSession = URLSession(configuration: theConfiguration, delegate: self, delegateQueue: nil)
  
  session = theSession     // Saved off to stored property
  
  let theTask = theSession.downloadTask(with: theURL)
  theTask.resume()


  func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

  print("we have a sesssion challenge")
  }
  
  func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

  print("we have a task challenge")
  }

Problem is, when connecting to a http: URL, it never calls either challenge delegate API. And we get this in the console:


Cannot start load of Task since it does not conform to ATS policy

Task finished with error - code: -1022


Any ideas on how to get this working? Our original app code still functions (I have the original app running on an older device and hitting our hosted server with a http: URL).


Also, the docs don't actually tell you what replaces connection:canAuthenticateAgainstProtectionSpace:. And looking up constants such as NSURLAuthenticationMethodServerTrust, show that they are not deprecated. But the docs then link you to a very old article showing you how the old system worked (entitled: Overriding TLS Chain Validation Correctly)


Thank you in advance for any tips.

Replies

You may need to read up on ATS (App Transport Security). Plain HTTP is no longer allowed without an exception. The OS converts the URL to HTTPS and requires strong security (TLS 1.2 etc.). If you allow users to enter arbitrary URLs, then you’ll have to use the NSAllowsArbitraryLoads blanket ATS exception. And be prepared to explain this choice to App Review.

Thank you very much for this info. Thankfully the code works a-ok if a user specificies https, so I think I'll push to having that be a requirement by our users. Otherwise, good to know about the possibility of making exceptions. But, yes, would rather not deal with any ATS exceptions, especially when considering App Review.