Hello there,
Starting from iOS 18.4, support was included for QWAC Validation and QCStatements.
Using the official QWAC Validator at: https://eidas.ec.europa.eu/efda/qwac-validation-tool
I was able to check that the domain "eidas.ec.europa.eu" has a valid QWAC certificate. However, when trying to obtain the same result using the new API, I do not obtain the same result.
Here is my sample playground code:
import Foundation
import Security
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
@MainActor
class CertificateFetcher: NSObject, URLSessionDelegate {
private let url: URL
init(url: URL) {
self.url = url
super.init()
}
func start() {
let session = URLSession(configuration: .ephemeral, delegate: self, delegateQueue: nil)
let task = session.dataTask(with: url) { data, response, error in
if let error = error {
print("Error during request: \(error)")
} else {
print("Request completed.")
}
}
task.resume()
}
nonisolated func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let trust = challenge.protectionSpace.serverTrust else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
if let certificates = SecTrustCopyCertificateChain(trust) as? [SecCertificate] {
self.checkQWAC(certificates: certificates)
}
let credential = URLCredential(trust: trust)
completionHandler(.useCredential, credential)
}
nonisolated func checkQWAC(certificates: [SecCertificate]) {
let policy = SecPolicyCreateSSL(true, nil)
var trust: SecTrust?
guard SecTrustCreateWithCertificates(certificates as CFArray, policy, &trust) == noErr, let trust else {
print("Unable to create SecTrust")
return
}
var error: CFError?
guard SecTrustEvaluateWithError(trust, &error) else {
print("Trust evaluation failed")
return
}
guard let result = SecTrustCopyResult(trust) as? [String : Any] else {
print("No result dictionary")
return
}
let qwacStatus = result[kSecTrustQWACValidation as String]
let qcStatements = result[kSecTrustQCStatements as String]
print("QWAC Status: \(String(describing: qwacStatus))")
print("QC Statements: \(String(describing: qcStatements))")
}
}
let url = URL(string: "https://eidas.ec.europa.eu/")!
let fetcher = CertificateFetcher(url: url)
fetcher.start()
Which prints:
QWAC Status: nil
QC Statements: nil
Request completed.
Am I making a mistake while using the Security framework? I would greatly appreciate any help or guidance you can provide.
Selecting any option will automatically load the page