Official info from Apple suggest creation of a certificate which means changes in server side which is not an option in my case.
Below I setup my app so requests can be done with an insecure certificate only to my server. This should be done only for development/testing purposes and should not be in production
1. Instruct ATS to ignore your server
EditInfo.plist
to have this (From Lory Lory in Stackoverflow):
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>self-signed-certificate.server.com</key>
<dict>
<!--Include to allow subdomains too-->
<key>NSIncludesSubdomains</key>
<true/>
<!--Include to allow ssl requests with self signed certificates and other insecure stuff-->
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
Official (and poor) documentation regarding NSAppTransportSecurity
can be found in InfoPlistKeyReference - CocoaKeys. Beware that key names are not even correct, see NSExceptionAllowsInsecureHTTPLoads
, instead of NSTemporaryExceptionAllowsInsecureHTTPLoads
, etc.
2. Make sure challenge is fulfilled in the WKWebView
If you are using WKWebView then you need to implement the navigation delegate. Remember, at least you should have a naive filter like below. Accepting everything is much more dangerous. This should be done only for testing/developing purposes.func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
if challenge.protectionSpace.host == "self-signed-certificate.server.com" {
let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, credential)
} else {
completionHandler(.performDefaultHandling, nil)
}
}
Now do setup the webview and do the request, everything should be ready for testing/developing now :)
webView = WKWebView()
webView.frame = CGRect(x: 0, y: 0, width: w, height: h)
webView.navigationDelegate = self
let request = URLRequest(url: URL(string: "https://self-signed-certificate.server.com")!)
webView.load(request)
3. Make sure challenge is fulfilled in the NSURLSession
If you are using the standard NSURLSession APIs then implement NSURLSessionDelegate method as below:func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
// Pass test server with self signed certificate
if challenge.protectionSpace.host == "self-signed-certificate.server.com" {
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
} else {
completionHandler(.performDefaultHandling, nil)
}
}
Now do the call (do not forget to set the delegate to your session!):
let session = NSURLSession(
configuration: NSURLSessionConfiguration.default,
delegate: object, // DO NOT FORGET YOUR OBJECT HERE!!
delegateQueue: nil)
let url = URL(string: "https://self-signed-certificate.server.com")!
let task = session.dataTask(with: url) { (data, response, error) in
...
}
task.resume()
3. Make sure challenge is fulfilled in Alamofire
If you are using Alamofire (one famous library wrapper for NSURLSession + some goodies) then implement something very similar as above.let sessionManager = SessionManager()
sessionManager.delegate.taskDidReceiveChallengeWithCompletion = { (_, _, challenge, completionHandler) -> Void in
// Pass test server with self signed certificate
if challenge.protectionSpace.host == "self-signed-certificate.server.com" {
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
} else {
completionHandler(.performDefaultHandling, nil)
}
}
Now simply do the call (Alamofire example)
sessionManager.request("https://self-signed-certificate.server.com", method: .get).response { response in
...
}
0 comments :
Post a Comment