Hi there, there a tons of examples out there, and I think I tried them all. ;-)
But still my app won't make a connection to a (just for testing!!) sub-domain where the cert is for another.
My code for the URLSession delegate is simply:
class UnsafeHTTPSRequestManager: NSObject, URLSessionDelegate {
private lazy var session: URLSession = {
let configuration = URLSessionConfiguration.default
return URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
}()
func performRequest(url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
let task = session.dataTask(with: url, completionHandler: completion)
task.resume()
}
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
// Akzeptiere jede Authentifizierungsherausforderung
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
}
let url = URL(string: "https://example.com")!
let manager = UnsafeHTTPSRequestManager()
manager.performRequest(url: url) { data, response, error in
if let error = error {
print("Fehler: \(error)")
} else if let data = data {
print("Daten empfangen: \(String(data: data, encoding: .utf8) ?? "Keine Daten")")
}
}
But still it returns with error like:
Fehler: Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorPeerCertificateChainKey=(....
On Apple platforms, the error usually includes a -98xx error code that can help with the diagnosis.
Finally, I generally recommend against overriding HTTPS server trust evaluation for testing. It’s too easy to leave that code in your real app and then ship a security vulnerability. Instead I prefer to set up a test CA, trust that CA, and have the test CA issue my test server a certificate. See:
Hi Quinn, thank you so much for looking into it!
Answers to your questions:
Platform is macOS.
Xcode 16A242d
Full text of error:
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorPeerCertificateChainKey=(
"<cert(0x11a054a00) s: synology i: Synology Inc. CA>"
), NSErrorClientCertificateStateKey=0, NSErrorFailingURLKey=https://example.com:5001/webapi/entry.cgi, NSErrorFailingURLStringKey=https://xexample.com:5001/webapi/entry.cgi, NSUnderlyingError=0x600002cbc4b0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x6000015e0370>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
"<cert(0x11a054a00) s: synology i: Synology Inc. CA>"
)}}, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask .<1>"
), _kCFStreamErrorCodeKey=-9802, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<1>, NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x6000015e0370>, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made.}
I second your warnings and concerns about untrustful certs. But my app will sometimes need to be able to talk to a server in the local network via its IP where the cert is bound to the (external) FQDN. So I think letting the user make an informed decision in this case would be the only way to deal with it here. And, yes, I've been chewing about Certificate trust prompt with URLS… | Apple Developer Forums for a while! ;-)
I will read about ATS and maybe post back here if my problems persist.
Your fundamental problem here is that URLSession doesn't use its delegate when you use the completionHandler form of dataTask(with:), so your handling is never called. Breakpoints in the delegate methods are always a good first step in investigating these sorts of issues.
Your fundamental problem here is that URLSession doesn't use
its delegate when you use the completionHandler form of dataTask(with:)
I think it’d be better to phrase this as “doesn’t always use”. It will use the delegate for certain things, and that includes authentication challenges.
Breakpoints in the delegate methods are always a good first
step in investigating these sorts of issues.
Absolutely!
Tino wrote:
Full text of error:
Note the the -9802 there. That’s errSSLFatalAlert. Unfortunately that doesn’t tell you a lot. The standard cause of this error is an alert coming from the server but macOS can also synthesise alerts.
But my app will sometimes need to be able to talk to a server
in the local network
As you might imagine, I’ve helped a lot of folks on DevForums with questions like this. My general advice is that you establish a working baseline and then tweak things from there. For example, the code in this post works for me (Xcode 16.1 on macOS 14.7.1). I recommend that you you:
Repeat the test at your end to confirm that.
Then put the code in your app. I expect it’ll fail due to ATS, and you can work on disabling that.
Then repeat the test for the accessory you’re targeting.