I have the following code to authenticate an iOS app to a MediaWiki server:
let task = NSURLSession.sharedSession()
task.configuration.HTTPAdditionalHeaders = ["Authorization": "Basic " + base64EncodedCredentials]
task.dataTaskWithURL(url!) {(data, response, error) in
dispatch_async(dispatch_get_main_queue(), {
if data != nil {
let result = NSString(data: data!, encoding: NSUTF8StringEncoding)
if resultIsValid(result) {
//Do authentication stuff
} else {
self.showLoginErrorMessage()
}
} else {
self.showLoginErrorMessage()
}
})
}.resume()
On iOS 8 this works perfect and I receive a HTTP 200 OK response. However, on iOS 9 I receive a 401 unauthorised. Unfortunately I do not have access to the server to see what it actually receives, and it is on an internal network, so I cannot link to the server. It uses HTTP basic access authentication, so I will assume that it should be the same as for any other server with that authentication type.
Is there any changes in the API from iOS 8 to 9 that could cause any issues like this? Could for instance other default headers like content type or user agent be changed/removed/added?
Edit: After testing with requests.in I have discovered that by adding a Content-Type, this is a part of the header in iOS 8, but not in iOS 9. In iOS 8 I can still get the request through without setting the Content-Type, but it is still weird that it is not present in the iOS 9 request.
I finally managed to figure it out! Turns out that in iOS 9 the HTTPAdditionalHeaders property of NSURLSessionConfiguration is read-only, and any changes to it will not be reflected in the current NSURLSession. On top of that, the four headers Authorisation
, Connection
, Host
and WWW-Authenticate
cannot be modified. Therefore, the only way to do basic access authentication in iOS 9 is by using NSURLCredential as proposed by quellish.
For anyone having the same problem, here is the final code I used to have my authentication working for both iOS 8 and iOS 9:
let url = NSURL(string: "https://subdomain2.subdomain1.example.com")
let credential = NSURLCredential(user: username, password: password, persistence: NSURLCredentialPersistence.ForSession)
let protectionSpace = NSURLProtectionSpace(host: url!.host!, port: 443, `protocol`: url!.scheme, realm: "subdomain2.example.com", authenticationMethod: NSURLAuthenticationMethodHTTPBasic)
NSURLCredentialStorage.sharedCredentialStorage().setCredential(credential, forProtectionSpace: protectionSpace)
let task = NSURLSession.sharedSession()
task.dataTaskWithURL(url!) {(data, response, error) in
if data != nil {
if responseIsValid(response) {
//Do authenticated stuff
} else {
self.showLoginErrorMessage()
}
} else {
self.showLoginErrorMessage()
}
}.resume()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With