Search code examples
swiftxcodeurlurlsession

Previously working URL Session code no longer works in Xcode 15


This code has worked fine for the past couple of years, but after dusting off an old project it no longer works in Xcode 15. I have the 'URLSessionDelegate' correctly set and below is a simplified method:

'''

    let user = "user"
    let pass = "pass"
    let token = "123456"
    let url = "https://192.168.17.254:7443/api/auth/login"

    let authUrl = URL(string: url)
    var authRequest = URLRequest(url: authUrl)
    authRequest.httpMethod = "POST"
    
    let authBody = ["username": user, "password": pass, "token": token]
    authRequest.httpBody = try! JSONSerialization.data(withJSONObject: authBody, options: .prettyPrinted)
    
    authRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
    authRequest.setValue("TOKEN=", forHTTPHeaderField: "Cookie")
    
    let authSessionConfig = URLSessionConfiguration.default
    let authSession = URLSession(configuration: authSessionConfig, delegate: self, delegateQueue: nil)
    authSession.dataTask(with: authRequest) { (data, response, error) in

            //Never reaches code here, no error no data

    }.resume
        

'''

I also have the delegate for 'didReceive challenge' which I have tried a few versions of from other questions on here ..

'''

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    print("didRecieve URLAuthenticationChallenge")
    
    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust  {
        print("send credential Server Trust")
        let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
        challenge.sender!.use(credential, for: challenge)
        
    }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic{
        print("send credential HTTP Basic")
        let defaultCredentials: URLCredential = URLCredential(user: "username", password: "password", persistence:URLCredential.Persistence.forSession)
        challenge.sender!.use(defaultCredentials, for: challenge)
        
    }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM{
        print("send credential NTLM")
        
    } else{
        challenge.sender!.performDefaultHandling!(for: challenge)
    }
}

'''

As I say this has worked fine previously but now I get API MISUSE errors, and it infers the completion handler wasn't called even though it was, as you can see the print statement in the output.

enter image description here

I am connecting to a local web server that uses HTTPS on port 7443 but doesn't have any certificates etc, I thought about posting a sample project but without the local web server you wouldn't be able to reproduce it. I suspect it some new ATS security in Xcode 15 but I have no idea what it wants me to do to fix it.


Solution

  • This code is incorrect:

        challenge.sender!.use(credential, for: challenge)
    

    It's not up to you to call use() here. It's up to you to call the completion handler (which is what the error is saying).

    The code you want here is:

    completionHandler(.useCredential, credential)
    

    Similarly for the other legs of your function.

    For complete details see Handling an authentication challenge.