How to set "xxxxxxxxxx token" for "authorization" in HTTP header in URLSession

The backend APIs I work with require a token to be sent with every request against an HTTP header Authorization

in this format - Token xxxxxxxxxx

.

Now I am doing the following.

var getRequest = URLRequest(url: url)
getRequest.addValue("Token xxxxxxxx", forHTTPHeaderField: "Authorization")

      

This works sometimes and sometimes, the header field Authorization

is removed when the request is sent. I have verified this using Charles proxy.

Apple documentation states the following.

The NSURLSession object is designed to handle various aspects of the HTTP protocol for you. As a result, you should not change the following headers: authorization, connection, host, WWW-authentication

As a solution to this, many suggest using the delegate method didReceiveAuthenticationChallenge

for the URLSession.

Here you need to pass in an instance URLSession.AuthChallengeDisposition

to communicate how you want to answer the challenge and an instance URLCredential

to pass the credentials to answer the authentication challenge.

I don't know how to do this and if I can instantiate URLCredential

that will add Token xxxxxxxx

for the title field Authorization

.

Can anyone more knowledgeable please help me how to solve this?

PS - All the code mentioned in this question is in Swift 3. This question asks something similar to what I have. But the answers given there don't work for me. And some of the questions asked on Apple related issues that do not allow adding titles for Authorization

have gone unanswered.

Edit:

Posting the appropriate code.

var getRequest = URLRequest(url: url)
getRequest.httpMethod = "GET"
getRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
getRequest.addValue("application/json", forHTTPHeaderField: "Accept")
let token = DataProvider.sharedInstance.token
getRequest.addValue("Token \(token)", forHTTPHeaderField: "Authorization")
let getTask = URLSession.shared.dataTask(with: getRequest) { (data, response, error) in
        if let data = data {
            print("--------GET REQUEST RESPONSE START--------")
            print("CODE: \((response as? HTTPURLResponse)?.statusCode ?? 0)")
            print("Response Data:")
            print(String(data: data, encoding: .utf8) ?? "")
            print("--------GET REQUEST RESPONSE END--------")
        }
}
getTask.resume()

      

Here I can confirm that the header field for "Authorization" is added to the request header dictionary.

But when I check what request gets to the server, the header field for "Authorization" is missing. Any thoughts?

+3


source to share


1 answer


I faced this same issue and found that my lack of trailing slash /

was the problem.

The server sent a response 301 Redirect

. URLSession

automatically follows the redirect but also discards the header Authorization

. This is probably due to the Authorization

"special status". According to the URLSessionConfiguration

documentation :

The URLSession object is designed to handle various aspects of the HTTP protocol for you. As a result, you should not change the following headers:

  • Resolution
  • Connection
  • Host
  • WWW-Authenticate

If a title is required Authorization

, use urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)

from URLSessionTaskDelegate

. This method is submitted by a new redirect request, allowing the header to be added back.



eg.

class APIClient: URLSessionTaskDelegate {
    let session: URLSession!
    initializeSession() {
        // Create a new session with APIClient as the delegate
        session = URLSession(configuration: URLSessionConfiguration.default,
                             delegate: self,
                             delegateQueue: nil)
    }

    // Perform the request
    func fetchRecords(handler: () => void) {
        var request = URLRequest(url: URL(string: "http://127.0.0.1:8000/api/employee/records")!)
        request.setValue(retrieveToken(), forHTTPHeaderField: "Authorization")
        session.dataTask(with: request, completionHandler: handler).resume()
    }

    // Implement URLSessionTaskDelegate HTTP Redirection method
    func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
        // Create a mutable copy of the new request, add the header, call completionHandler
        var newRequest = request
        newRequest.addValue(retrieveToken(), forHTTPHeaderField: "Authorization")
        completionHandler(newRequest)
    }
}

      

IMPORTANT NOTE!

It's a bad idea to blindly trust a redirect. You need to make sure that the URL you are redirected to is the same domain as the original request. I left this from my example code for brevity.

+3


source







All Articles