Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

URLSession not working with URLCredential

Tags:

ios

swift

swift3

I have an API I am trying to connect to and the server is Windows Authentication.

I am trying to use URLSession with URLCredential with the delegate methods

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void){

        var disposition: URLSession.AuthChallengeDisposition = URLSession.AuthChallengeDisposition.performDefaultHandling

        var credential:URLCredential?

        print(challenge.protectionSpace.authenticationMethod)

        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)

            if (credential != nil) {
                disposition = URLSession.AuthChallengeDisposition.useCredential
            }
            else
            {
                disposition = URLSession.AuthChallengeDisposition.performDefaultHandling
            }
        }
        else
        {
            disposition = URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge
        }

        completionHandler(disposition, credential);
    }

This code runs twice as after doing some printing is because there are two Authentication Methods:

NSURLAuthenticationMethodServerTrust and NSURLAuthenticationMethodNTLM when it runs through the NSURLAuthenticationMethodServerTrust everything is fine, but when it runs NSURLAuthenticationMethodNTLM I get an error on this line:

credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)

saying this:

fatal error: unexpectedly found nil while unwrapping an Optional value

but only when I change this condition from

if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {

to

if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM {

What Am I doing wrong?

Here is the method I am using to try to connect to that API

func loginUser(_ username: String, password: String, completion: @escaping (_ result: Bool) -> Void)
    {
        //Create request URL as String

        let requestString = String(format:"%@", webservice) as String

        //Covert URL request string to URL

        guard let url = URL(string: requestString) else {
            print("Error: cannot create URL")
            return
        }

        //Convert URL to URLRequest

        let urlRequest = URLRequest(url: url)

        print(urlRequest)

        //Add the username and password to URLCredential

        credentials = URLCredential(user:username, password:password, persistence: .forSession)

        print(credentials)

        //Setup the URLSessionConfiguration

        let config = URLSessionConfiguration.default

        //Setup the URLSession

        let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)

        //Prepare the task to get data.

        let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in

            DispatchQueue.main.async(execute: {

                print(error!)

                if(error == nil)
                {
                    completion(true)
                }
                else
                {
                    completion(false)
                }

            })

        })

        //Run the task to get data.

        task.resume()

    } 
like image 679
user979331 Avatar asked Dec 06 '16 15:12

user979331


1 Answers

In the Apple documentation for URLProtectionSpace.serverTrust, it says:

nil if the authentication method of the protection space is not server trust.

So, you are trying to unwrap an optional value of nil, which of course would cause a crash.

In your case, you could probably just replace the entire function with (untested):

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void){

    var disposition: URLSession.AuthChallengeDisposition = URLSession.AuthChallengeDisposition.performDefaultHandling

    print(challenge.protectionSpace.authenticationMethod)

    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
        disposition = URLSession.AuthChallengeDisposition.performDefaultHandling
    }
    else
    {
        disposition = URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge
    }

    completionHandler(disposition, credential);
}
like image 112
Coder-256 Avatar answered Oct 18 '22 16:10

Coder-256