Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between NSURLSession on iOS 8 and iOS 9?

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.

like image 393
Jorn Avatar asked Oct 19 '22 02:10

Jorn


1 Answers

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() 
like image 173
Jorn Avatar answered Oct 30 '22 17:10

Jorn