I'm using URLSession and Combine to monitor and control a device on my internal network. One URL to retrieve JSON data is https://ip_address/api/v1/items
The device has a self-signed certificate so I'm getting an error that the certificate is invalid. I need my code to ignore the certificate and retrieve the data.
Is there a good solution to accept this self-signed certificate with Combine and URLSession?
Here is the code that makes the HTTPS get request.
The device has a self-signed certificate so I'm getting an error that the certificate is invalid. I need my code to ignore the certificate and retrieve the data.
Is there a good solution to accept this self-signed certificate with Combine and URLSession?
Here is the code that makes the HTTPS get request.
Code Block func sendControllerGetRequest(uri: String) -> PassthroughSubject<Data, Never> { getRequestPublisher = PassthroughSubject<Data, Never>() var urlRequest = URLRequest(url: URL(string: self.baseURI+uri)!) urlRequest.httpMethod = "GET" urlRequest.setValue("Bearer \(self.directorBearerToken)", forHTTPHeaderField: "Authorization") getRequestCancellable = URLSession.shared.dataTaskPublisher(for: urlRequest) .map{ $0.data } .sink(receiveCompletion: { completion in switch completion { case .failure(let error): print("sendControllerGetRequest error") print(error) case .finished: print("sendControllerGetRequest finished") break } }, receiveValue: { requestDetails in print(String(data: requestDetails, encoding: .utf8)!) print("sendControllerGetRequest()") self.getRequestPublisher.send(requestDetails) self.getRequestPublisher.send(completion: .finished) } ) return getRequestPublisher }
Here is a solution.
urlSession is called twice. The second time challenge.protectionSpace.serverTrust is nil. I'm still trying to fully understand this so any help is appreciated. This implementation is not secure and should only be used for testing.
This code has been built and tested with Swift 5, iOS 14 running on the simulator in Xcode 12.2.
urlSession is called twice. The second time challenge.protectionSpace.serverTrust is nil. I'm still trying to fully understand this so any help is appreciated. This implementation is not secure and should only be used for testing.
This code has been built and tested with Swift 5, iOS 14 running on the simulator in Xcode 12.2.
Code Block import Foundation import Combine class myClass: NSObject, URLSessionDelegate { var ip: String var directorBearerToken: String var baseURI: String private var getRequestCancellable: AnyCancellable? private var getRequestPublisher = PassthroughSubject<Data, Never>() init(ip: String, token: String) { self.ip = ip self.directorBearerToken = token self.baseURI = "https://\(ip)" } // Get a JSON data with all the items func getAllItemInfo() -> PassthroughSubject<Data, Never> { let test = sendControllerGetRequest(uri: "/api/v1/items") return test } func sendControllerGetRequest(uri: String) -> PassthroughSubject<Data, Never> { print("sendControllerGetRequest") getRequestPublisher = PassthroughSubject<Data, Never>() var urlRequest = URLRequest(url: URL(string: self.baseURI+uri)!) urlRequest.httpMethod = "GET" urlRequest.setValue("Bearer \(self.directorBearerToken)", forHTTPHeaderField: "Authorization") let configuration = URLSessionConfiguration.default let session = URLSession(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main) getRequestCancellable = session.dataTaskPublisher(for: urlRequest) .map{ $0.data } .sink(receiveCompletion: { completion in switch completion { case .failure(let error): print("sendControllerGetRequest error") print(error) case .finished: print("sendControllerGetRequest finished") break } }, receiveValue: { requestDetails in print(String(data: requestDetails, encoding: .utf8)!) print("sendControllerGetRequest()") self.getRequestPublisher.send(requestDetails) self.getRequestPublisher.send(completion: .finished) } ) return getRequestPublisher } func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { if challenge.protectionSpace.serverTrust == nil { completionHandler(.useCredential, nil) } else { let trust: SecTrust = challenge.protectionSpace.serverTrust! let credential = URLCredential(trust: trust) completionHandler(.useCredential, credential) } } }