Freestyle076
Freestyle076

Reputation: 1556

Swift NSURLSession HTTPS Self Sign - Request never reaches server

I'm having troubles performing a HTTPS post request to my django rest api. I have django-sslserver running to expose the api on port 8000. Things seem fine, when I make a request in a browser https://server-ip-addr:8000/api_view/ my browser complains "Hey! This guys certificate is self signed!" I say "yeah I know, that's me" and continue into the dangerous response.

Anyways I'm attempting to perform the same in Swift for an iOS application. I've found from this link here on implementing NSURLSession delegate protocols/functions NSURLSessionDelegate.URLSession() and NSURLSessionTaskDelegate.URLSession(). I've tweaked the example so that it atomically performs login attempts to my sslserver.

I've done so in the following code, a class implementing the two protocols above designed to pass username/password credentials to the server and wait for a response.

class SecureLogin: NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate {

    func attemptLogin(username: String, password: String,
        callback: ((NSData!,NSURLResponse!,NSError!) -> Void)?) {
        
            println("inside attempt login")
        
            var request = NSMutableURLRequest(URL: NSURL(string: "https://147.222.164.91:8000/ldapauth/")!)
            request.HTTPMethod = "POST"

        
            var params = ["username":username, "password":password] as Dictionary<String, String>
        
            var err: NSError?
            request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
            request.addValue("application/json", forHTTPHeaderField: "Content-Type")
            request.addValue("application/json", forHTTPHeaderField: "Accept")
        
            var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
            var session = NSURLSession(configuration: configuration,
                delegate: self,
                delegateQueue:NSOperationQueue.mainQueue())
            var task = session.dataTaskWithRequest(request,callback)
        
            task.resume()
    }

    func URLSession(session: NSURLSession,
        didReceiveChallenge challenge: NSURLAuthenticationChallenge,
        completionHandler: (NSURLSessionAuthChallengeDisposition,NSURLCredential!) -> Void) {
            println("Challenge received")
            completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust))
    }

    func URLSession(session: NSURLSession,
        task: NSURLSessionTask,
        willPerformHTTPRedirection response: NSHTTPURLResponse,
        newRequest request: NSURLRequest,
        completionHandler: (NSURLRequest!) -> Void) {
            println("Redirection received")
            var newRequest : NSURLRequest? = request
            println(newRequest?.description)
            completionHandler(newRequest)
    }
}

So I go to attempt to perform the attemptLogin() function, providing the simple callback function to confirm a response

var gatekeeper = SecureLogin()

gatekeeper.attemptLogin(username, password: password, callback: {data, response, error -> Void in

    println("inside gatekeeper")

}

println("beginning wait")

sleep(25)

I sleep the thread 25 seconds to keep the process alive long enough for the response to come in.

The output on the console looks like:

inside attempt login

beginning wait

Then the program dies, no response/"inside gatekeeper" message received, my django server terminal doesn't show any received requests either. I ran a sanity check: I've commented out the implementations of the delegate methods and the server receives the request, responds with:

inside attempt login

beginning wait

2015-01-27 11:29:37.192 LdapAuthSecure[12783:1475994] NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9812)

the expected error when there is no protocol for handling an authorization challenge.

Can anyone spot any problems with my implementation of the NSURLSession or its delegates? I find it very strange that the request doesn't even reach the server. Thank you for any help!

Upvotes: 4

Views: 2060

Answers (2)

dgatwood
dgatwood

Reputation: 10417

If this is iOS 9, and if you built your app against the iOS 9 (or later) SDK, you'll also have to tweak your Info.plist file to tell it to allow insecure loads. Otherwise, the URL loading system won't get as far as calling your authentication handler.

Upvotes: 1

GenericName
GenericName

Reputation: 41

so I've never coded for iOS but I do know from memory that native apps will not popup a dialog nor accept self signed certificates by default.

If you own a domain (or if not, it's probably easier) you can get a free certificate from https://www.startssl.com/ or https://buy.wosign.com/free/

Or you can install the self signed certificate by emailing it to your phone and then opening it.

You can remove the self signed certificate from the profiles page in Settings.

I also found this answer for you: https://stackoverflow.com/a/22674004/4837003 But that looks like it will disable validation.

Upvotes: -1

Related Questions