iosswifturlsessionurlrequest

400 error when downloading file with "Authorization" header


The server returning a json file that is:

{"ctrl":{"code":400,"text":"Not valid Access token","ts":"2020-03-05T11:54:01.547Z"}}

Code:

public func startDownload(url: URL, pathURL: URL) {
        let accessToken: String! = "Bearer \(Constants.access_token)"
        self.dirURL = pathURL
        var request = URLRequest(url: url)
        guard let token = accessToken else { return }
        request.addValue(token, forHTTPHeaderField: "Authorization")
        downloadTask = backgroundSession.downloadTask(with: request)
        downloadTask.resume()
}

FYI: access token is valid, it is working with Postman.


Solution

  • You're going to have a problem because, unfortunatelly, there's no good solution to this issue. Authorization is one of the Reserved HTTP Headers and setting it either in URLRequest header, or in URLSessionConfiguration.httpAdditionalHeaders may simply not work:

    If you set a value for one of these reserved headers, the system may ignore the value you set, or overwrite it with its own value, or simply not send it.

    One might expect you could provide this token in URLSessionTaskDelegate method urlSession(_:task:didReceive:completionHandler:) which handles authentication challenges, but in there you need to provide a URLCredential object, and sadly it doesn't have a constructor that takes a Bearer token, so that's a no-go.

    So basically, short of writing your own URLProtocol implementation, your best bet would be to send the token in some additional, custom, header field and have the server grab it from there (if you have control over server code). Source