I’m trying to connect to a smart switch using URLSession. The switch uses http Digest Authentication which should trigger a call to delegate function urlSession(_: URLSession, task: URLSessionTask, didReceive: URLAuthenticationChallenge ...
, but that function is never called.
In testing my code using a Digest Authentication testing website the challenge delegate function is called as expected. So it seems that URLSession is not responding to the way the smart switch company implemented Digest Authentication.
I can successfully connect to the switch by manually handling the Digest Authentication by building and setting the Authentication
header, but this only works in an Xcode playground. In an iOS app setting the Authentication
header has no effect, as noted in the documentation.
My question is: Is there another way to add the Digest Authentication userId and password to the URLSession other than in an Authentication Challenge delegate method?
If not, is there another, perhaps lower level, way to set the Authentication
header?
Any help is greatly appreciated.
Here is some testing code that can be run in an Xcode playground:
import Foundation
class Foo: NSObject {
public func connect() {
// this url calls the challenge delegate function
let urlS = "http://httpbin.org/digest-auth/undefined/undefined/undefined"
// this smart switch url does not call the challenge delegate function
// let urlS = "http://192.168.1.99/relay/0?turn=on&timer=30"
guard let url = URL(string: urlS) else {
return
}
var request = URLRequest(url: url)
let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
session.dataTask(with: request).resume()
}
}
extension Foo: URLSessionTaskDelegate {
func urlSession(_: URLSession, task: URLSessionTask, didReceive: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
{
print("Authentication Challenge Delegate Called")
// never gets called
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
let msg = (error != nil) ? String(describing: error) : "nil"
print("something went wrong: (msg)")
// gets called with error = nil
}
}
let foo = Foo()
foo.connect()