1

I'm having this issue where Alamofire is using an incorrect authorization header when sending a request to my server.

The first time I use the username and password and everything works fine. Then if I change the username and password quickly and retry the request as a different user it completely fails. When I print the HTTP headers in the iOS console it is correct every time. But when my server prints the headers it's different then the headers I printed on the iOS console.

If I wait a couple of minutes before changing users it seems to work fine. But if I do it within a minute the authorization header that is printed on the iOS device is different then the one the server receives. So it's using the old authorization information not the new one.

Below is the code I'm using.

func reloadData() {
    print("Reloading data!!")   
    let keychain = KeychainSwift()

    let email: String = keychain.get("email")!
    let password: String = keychain.get("password")!

    URLCache.shared.removeAllCachedResponses()

    let sessionManager = Alamofire.SessionManager.default
    sessionManager.session.configuration.requestCachePolicy = .reloadIgnoringLocalCacheData


    let loginString = String(format: "%@:%@", email, password)
    let loginData = loginString.data(using: String.Encoding.utf8)!
    let base64LoginString = loginData.base64EncodedString()

    print(base64LoginString)

    let headers: HTTPHeaders = ["Authorization": "Basic \(base64LoginString)"]



    sessionManager.request("http://IPHERE:3000/api/items", headers: headers).validate().responseJSON { response in
        switch response.result {

        case .success(let value):

            let json = JSON(value)
            print("JSON: \(json)")

            for item in json.array! {

                let title: String? = item["title"].stringValue
                self.titles.append(title!)
                self.colors.append(UIColor.blue)
            }

            self.tableView.reloadData()

        case .failure(let error):
            print ("My Error")
            print (error)
            let alertController = UIAlertController(title: "Error", message: "Error, please try again or contact support", preferredStyle: UIAlertControllerStyle.alert)
            let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
            }
            alertController.addAction(okAction)
            self.present(alertController, animated: true, completion: nil)
        }
    }
}

So if I call this function the first time it works fine. base64LoginString is correct and matches what the server receives. If I logout and enter a different users information, base64LoginString is different then the original which is correct and is expected. But that request when it gets sent to the server still has the old base64LoginString value instead of the new one. So the server returns the information for the first user even tho we are now logged in as the second user.

So somewhere between printing base64LoginString and the server receiving the request something fails. It's almost like it caches the headers or something, which doesn't make sense at all.

Also for reference I'm using Node, Express, and Passport.js to handle web requests and auth on the backend. Let me know if I can provide any more information to help out.

Charlie Fish
  • 18,491
  • 19
  • 86
  • 179
  • I read your question really fast since i don't use Alamofire. Could it be something like this : http://stackoverflow.com/questions/32893800/alamofire-ignore-cache-control-headers and if you read the documentation: **'Response Caching** Response Caching is handled on the system framework level by URLCache. It provides a composite in-memory and on-disk cache and lets you manipulate the sizes of both the in-memory and on-disk portions. By default, Alamofire leverages the shared URLCache. In order to customize it, see the Session Manager Configurations section.' –  Feb 24 '17 at 22:27
  • or this: http://stackoverflow.com/questions/32199494/how-to-disable-caching-in-alamofire –  Feb 24 '17 at 22:30
  • Yeah I thought that's what `sessionManager.session.configuration.requestCachePolicy = .reloadIgnoringLocalCacheData` was doing. Or `URLCache.shared.removeAllCachedResponses()` – Charlie Fish Feb 24 '17 at 22:31
  • I am not sure since I can't test your code I don't use alamofire, but there are many threads about it with different examples, have you checked them and tried the different suggestions? I found one more interesting here: http://stackoverflow.com/questions/37535432/how-to-disable-the-urlcache-completely-with-alamofire I think it might be something with your manager instantiation? –  Feb 24 '17 at 22:32
  • Does it really make sense that it's caching the response tho? It's hitting my server and the server is responding with a 200 status code. Even in the response section it says it got a 200 status code back. Not like a 304 or anything like that. – Charlie Fish Feb 24 '17 at 22:36
  • Not sure how it works with Alamofire other than the suggestions above. It seems you are passing the headers correctly in your code. Not sure about the framework but have you tried a simple request with your header and see if that makes any difference using this method : Alamofire.request("IPHERE:3000/api/items";, headers: headers).responseJSON { response in " Also I noticed youve already made a thread about this: http://stackoverflow.com/questions/42431077/disable-cache-alamofire-ios you should not create multiple questions for the same question as a bump-up. –  Feb 24 '17 at 22:53
  • My last question kept getting really far off topic. This seems like a completely new issue. Could be totally wrong. To me now it doesn't seem like a caching issue. Which is what my original question was regarding. Sorry if that is totally wrong. – Charlie Fish Feb 24 '17 at 22:55

1 Answers1

3

Not sure if its your same scenario but in my case the cache result was caused for a cookie. By removing all the cookies before doing the authentication request (E.g when the user signs out) worked for me. I guess it could be your issue since the backend I'm doing the sign in requests are also using Node and Express.

You can try this code to remove all cookies:

let cookieStore = HTTPCookieStorage.shared
for cookie in cookieStore.cookies ?? [] {
    cookieStore.deleteCookie(cookie)
}
odm
  • 888
  • 1
  • 14
  • 22