I want to connect to a Phillips Hue Api (something like that: https://<ip_address>/clip/v2/ressource/device).
The issue is that on the software Postman (to test), Phillips Hue says to disable "SSL Certificate Verification".
When I try to call with URLRequest in my app the same url, using URLSessions, I get this error:
Domain=kCFErrorDomainCFNetwork Code=-1202 NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “<ip_address_of_Hue_bridge>” which could put your confidential information at risk.
I read those articles:
I don't want to disable all HTTPS server trust evaluation, it’s super insecure. I want to customise the trust evaluation to let the connection through to be as secure as possible.
But I don't really know how to do this with URLSession or another thing if needed. Phillips Hue is giving what looks like a pem certificate (see in attachements). I don't know how to implement this in my URLSession request.
Thank you for your help
Here a code I implemented and working:
class NSURLSessionPinningDelegate: NSObject, URLSessionDelegate {
let certFileName = "phillips-hue-cert"
let certFileType = "pem"
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
if let serverTrust = challenge.protectionSpace.serverTrust {
var secresult = SecTrustResultType.invalid
let status = SecTrustEvaluate(serverTrust, &secresult)
if(errSecSuccess == status) {
if let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0) {
let serverCertificateData = SecCertificateCopyData(serverCertificate)
let data = CFDataGetBytePtr(serverCertificateData);
let size = CFDataGetLength(serverCertificateData);
let certificateOne = NSData(bytes: data, length: size)
let filePath = Bundle.main.path(forResource: self.certFileName,
ofType: self.certFileType)
if let file = filePath {
if let certificateTwo = NSData(contentsOfFile: file) {
completionHandler(URLSession.AuthChallengeDisposition.useCredential,
URLCredential(trust:serverTrust))
return
}
}
}
}
}
}
completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
}
}
Then I replaced UrlSession by:
let session = URLSession(
configuration: URLSessionConfiguration.ephemeral,
delegate: NSURLSessionPinningDelegate(),
delegateQueue: OperationQueue.main)
session.dataTask(with: request) { (data, response, error) in .......
That's working for me. I hope it's a good solution and a secured one. It looks good to me. If anyone as a better solution, I will be happy to hear about it.