Connect to a Server with Invalid Certificate using NSURLSession (swift2,xcode7,ios9)
Solution 1
Take a look at this article.Shipping an App With App Transport Security particularly the sections about self-signed certificates.
You'll most likely need the delegate method of the form,
func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
completionHandler(
.UseCredential,
NSURLCredential(trust: challenge.protectionSpace.serverTrust!)
)
}
Adding this to my own comms class that uses NSURLSession fixed the issue.
Solution 2
When creating the URL Session, use the initializer, that sets the delegate along with the configuration, like below:
let urlSession = URLSession(configuration: urlSessionConfiguration, delegate: self, delegateQueue: nil)
Then, implement the following delegate method, it should work.
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let urlCredential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, urlCredential)
}
However, it is very important to note, that this is a security issue, and we should not be trying to connect to servers with invalid certificates.
Solution 3
Many of the answers are almost there, but not quite. So here is what worked for me on Xcode 12.4
In my Requesting Class
let session: URLSession
let sessionDelegate: HTTPRequestDelegate
private init() {
let configuration = URLSessionConfiguration.default
// Some more configuration settings
// ...
sessionDelegate = HTTPRequestDelegate()
session = URLSession(configuration: configuration,
delegate: sessionDelegate,
delegateQueue: nil)
}
Where:
public class HTTPRequestDelegate: NSObject, URLSessionDelegate
{
// Get Challenged twice, 2nd time challenge.protectionSpace.serverTrust is nil, but works!
public func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
print("In invalid certificate completion handler")
if challenge.protectionSpace.serverTrust != nil {
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
} else {
completionHandler(.useCredential, nil)
}
}
}
Comments
-
cakes88 almost 2 years
I'm using Xcode 7, Swift 2, and iOS9. I want to connect to a web service using NSURLSession but I get the following error when I try to connect:
2015-10-13 16:07:33.595 XCTRunner[89220:4520715] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813) 2015-10-13 16:07:33.604 XCTRunner[89220:4520571] Error with connection, details: Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “domainapi.com” which could put your confidential information at risk." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x7fac7b6facc0>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?,
Here is my code:
func request( dataPost : String, successHandler: (response: String) -> Void)-> String { let destination:String = "https://domainapi.com:8743/WebService/sendData" let request = NSMutableURLRequest(URL: NSURL(string: destination as String)!) request.HTTPMethod = "POST" let postString = dataPost request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding) request.setValue("0", forHTTPHeaderField: "Content-Length") request.setValue("application/xml", forHTTPHeaderField: "Content-Type") request.setValue("gzip,deflate", forHTTPHeaderField: "Accept-Encoding") request.setValue("Keep-Alive", forHTTPHeaderField: "Connection") NSLog("Body is: %@", request.HTTPBody!) NSLog("Request is: %@", request.allHTTPHeaderFields!) NSLog("URL is: %@", destination) let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in if error != nil { NSLog("Error with connection, details: %@", error!) return } let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding) successHandler(response: responseString as String!); NSLog("Data received: %@", data!) } task.resume() return "worked" } func viewDidLoad() { let dataPost : String = "<webservices>xml data sending</webservices>" request(dataPost, successHandler: { (response) in let text = response print(text) });
I've looked into
NSURLAuthenticationChallenge
but I can't seem to figure that out with the code I currently have in place. So my question is how can I connect to the server anyway? I've already tried adding the domain to myNSAppTransportSecurity
in Info.plist but that did not work. Turning onNSAllowsArbitraryLoads
didn't work either. Any help would be appreciated.-
Code Different over 8 yearsCheck out this question on SO: stackoverflow.com/questions/933331/…
-
cakes88 over 8 years@ZoffDino that's using NSURLConnection which is deprecated in iOS8. I'd like to use NSURLSession if possible.
-
Jacob King over 8 yearsThe AFNetworking library has excellent support for this, I would recommend checking it out.
-
-
FractalDoctor over 8 yearsI don't see how this helps, as you're really just bypassing the IP addresses that the app talks to and not anything to do with server certificates?
-
Sumit over 7 yearsi added delegate but this method never called in swift 3, any other solutions without using alamofire or any other lib?
-
Jayprakash Dubey about 7 years@Marcelo : NSAllowsArbitaryLoads key when set to true will allows access to all unsecured URLs. So what is the point of having CER file for security?
-
Muhammad Danish Qureshi over 2 yearsThanks...! This answer is very useful and worked with me in Swift 5 and Xcode 13.1.