Search code examples
iosswiftrestios9alamofire

Updating iOS 8 -> iOS 9 (New version of Swift) Causes REST API Issues (401 Error) using Alamofire


After I updated my code from iOS 8 to iOS 9, my alamofire rest calls started giving me 401 errors. The code works perfectly fine in iOS 8 but not in iOS 9.

Thanks for the help.

The fullUrl and token variables are set correctly.

let fullUrl = Config.baseUrl + endpoint
let manager = Manager.sharedInstance
        manager.session.configuration.HTTPAdditionalHeaders = [
            "Content-Type": "application/json",
            "Authorization": "Basic \(token)"
        ]

        manager.request(.GET, fullUrl).response {
            (request, response, data, error) in
            if let response = response {
                print("GET REQUEST: \(response.statusCode)")
                print(response.debugDescription)
//                print(response.description)
                if response.statusCode == 200 ||
                    response.statusCode == 201 {
                        let json = JSON(data: data!)
                        success?(json: json)
                }
                else if response.statusCode == 403 {
                    UserInfo.logOut()
                    failure?(error: .ExpiredToken)
                }
                else {
                    failure?(error: .InvalidLogin)
                }

            } else {
                failure?(error: .ConnectionUnavailable)
                //                    self.log(request, res: response, err: error)
            }
        }

In my info.plist I have also added the code to handle App Transport Security

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAppTransportSecurity</key>
        <dict>
            <key>NSAllowsArbitraryLoads</key>
            <true/>
        </dict>
    </dict>

Please let me know if there is any confusion with the question.


Solution

  • You might be running into the same issue I had: https://github.com/Alamofire/Alamofire/issues/798

    Your URL might return a redirect, in wich case the "Authorization"-Header is not passed along. You can test this when you look at the data sent over the network using Wireshark or a similar tool.

    If you don't want to do the network debugging, you can just try the following and see if you're request work. BTW: You should not use HTTPAdditionalHeaders.

    Try this:

    // Configure special-handling of redirects (you only need to do this once)
    Alamofire.Manager.sharedInstance.delegate.taskWillPerformHTTPRedirection = { session, task, response, request in
        var redirectedRequest = request
    
        if let
            originalRequest = task.originalRequest,
            headers = originalRequest.allHTTPHeaderFields,
            authorizationHeaderValue = headers["Authorization"]
        {
            let mutableRequest = request.mutableCopy() as! NSMutableURLRequest
            mutableRequest.setValue(authorizationHeaderValue, forHTTPHeaderField: "Authorization")
            redirectedRequest = mutableRequest
        }
    
        return redirectedRequest
    }
    
    
    // Your code, slightly adapted
    let fullUrl = Config.baseUrl + endpoint
    let headers = [
                "Content-Type": "application/json",
                "Authorization": userData.userAPIKey!,
            ]
    Alamofire.request(.GET, fullUrl, parameters: nil, encoding: .URL, headers: headers)
      .response { (request, response, data, error) -> Void in
           if let response = response {
                print("GET REQUEST: \(response.statusCode)")
                print(response.debugDescription)
                //                print(response.description)
                if response.statusCode == 200 ||
                    response.statusCode == 201 {
                        let json = JSON(data: data!)
                        success?(json: json)
                }
                else if response.statusCode == 403 {
                    UserInfo.logOut()
                    failure?(error: .ExpiredToken)
                }
                else {
                    failure?(error: .InvalidLogin)
                }
    
            } else {
                failure?(error: .ConnectionUnavailable)
                //                    self.log(request, res: response, err: error)
            }        
      }