I am attempting to download a PDF from a URL.
private func downloadSessionWithFileURL(_ url: URL){
var request = URLRequest(url: url)
request.addValue("gzip, deflate", forHTTPHeaderField: "Accept-Encoding")
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
session.downloadTask(with: request).resume()
}
This calls its delegate method
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.previousFailureCount > 0 {
completionHandler(Foundation.URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
}
if let serverTrust = challenge.protectionSpace.serverTrust {
completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: serverTrust))
} else {
print("unknown state. error: \(String(describing: challenge.error))")
}
}
The URLAuthenticationChallenges protectionSpace is always serverTrust. When the URL of the PDF is attempted to be accessed it redirects user to a login screen. I would have thought there would be another call to
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
requiring user to enter their credentials but there isn't. So the download task attempts to download the contents of the redirected URL which is a login screen.
My Questions are.
What triggers a URLAuthenticationChallenge for a username and password. is it a specific header value in the HTML?
Which URLAuthenticationChallenge protectionSpace should I be expecting for a username password request from a server.
Some basics of SSL:
If you an have https connection, these methods will be triggered. These are for security purpose to prevent the man in the middle attack. For e.g, I can set up charles proxy server, install the public certificate on simulator/device and can monitor all the request that the app is sending to the actual server and thus obtain the sensitive information(API Keys, token, request Headers, request body etc) which I need to hide from attackers.
You can either Compare the server certificate with the local certificates that you have in your apps:
or you can compare the public keys:
Comparing public keys is a better approach as when comparing certificates, you have to keep a copy of the local certificate in the app and when the certificates expires which will have to update the certificates in the app, which require an update in the app store.