The iOS app I'm working on is using Alamofire 4.9.1 and the following code executes without any issues in iOS 14 and below, but not iOS 15.
dataProvider.sessionDelegate.sessionDidReceiveChallenge = { _, challenge in
print("CHALLENGE ACCEPTED")
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {
return (URLSession.AuthChallengeDisposition.useCredential,
cert.urlCredential())
}
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
return (URLSession.AuthChallengeDisposition.useCredential,
URLCredential(trust: challenge.protectionSpace.serverTrust!));
}
return (URLSession.AuthChallengeDisposition.performDefaultHandling,
Optional.none)
}
, where cert is a .pfx certificate initialized just before this.
This is preventing the app from accessing information on a server with TLS 1.2 certificate based authentication. In iOS 13 and 14 (supported iOS versions start at 13) the print statement executes, but not in iOS 15 for some reason. In iOS 13 and 14, in Alamofire's SessionDelegate.swift,
open func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
gets called, but in iOS 15 that is replaced by a call to
open func urlSession(
_ session: URLSession,
task: URLSessionTask,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
Any idea as to what can be causing this and how to address it? Thank you in advance.
I managed to solve the issue by modifying the SessionDelegate.swift file of the Alamofire pod itself. Namely, I initialized the certificate in the SessionDelegate.swift file and passed its urlCredential property to the task delegate's credential property in
open func urlSession(
_ session: URLSession,
task: URLSessionTask,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
and voilà, it worked.
So I re-defined the class (PKCS12) that lets me initialize the certificate inside the SessionDelegate.swift file and the body of the above function now looks like this:
if let taskDidReceiveChallenge = taskDidReceiveChallenge {
let result = taskDidReceiveChallenge(session, task, challenge)
completionHandler(result.0, result.1)
} else if let delegate = self[task]?.delegate {
// this gets executed in iOS 15 and we need to get a credential in order for the delegate to successfully set the disposition required for getting data from the server
let cert = PKCS12.init(mainBundleResource: "\(certNameHere)",
resourceType: "pfx",
password: "%^&^%*&")
delegate.credential = cert.urlCredential()
delegate.urlSession(
session,
task: task,
didReceive: challenge,
completionHandler: completionHandler
)
} else {
urlSession(session, didReceive: challenge, completionHandler: completionHandler)
}
This has solved the issue for us and I hope it is of help to others who may experience similar issues with iOS 15 and Alamofire 4.9.1. Thank you for reading.