Reputation: 1556
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
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
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