Skip to content

Alamofire 2.0 Authorization-Header not sent iOS 9 #788

Closed
@eburi

Description

@eburi

Using

PODS:
  - Alamofire (2.0.1)

I have this strange issue, that the Authorization-Header isn't sent for some requests.

Just upgraded to Alamofire 2.0.1 from 1.3. Had the same problem with the 1.3 on iOS 9 - one specific request does not get the Header sent...

I tried both ways of setting the header. a) Using a dedicated Manager created with:

    func createManagerWithAuthHeader(authHeader:String) -> Manager {
        var addedHeaders = Manager.defaultHTTPHeaders
        addedHeaders["Authorization"] = authHeader

        NSLog("Authorization-Header: \(authHeader)")
        let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
        configuration.HTTPAdditionalHeaders = addedHeaders        
        return Manager(configuration: configuration)
    }

Now I just keep the different values for Authentication and apply them depending on the route:

    // Router to generate Requests
    enum Router: URLRequestConvertible {
        static let BASE_URL = "************"

        // Possible Requests
        ....
        case Category(String)
        case Criterias(String)
        ....

        var URLRequest: NSMutableURLRequest {
            let (path, method, userAuth, parameters, encoder): (String, String, Bool, [String: AnyObject], Alamofire.ParameterEncoding) = {
                switch self {
                .....
                case .Category(let catId):
                    return ("/categories/\(catId)/", "GET", false, [:], Alamofire.ParameterEncoding.URL)
                case .Criterias(let catId):
                    return ("/categories/\(catId)/criteria", "GET", false, [:], Alamofire.ParameterEncoding.URL)
                .....
                }
            }()

            let requestUrl = NSURL(string: Router.BASE_URL)
            let request = NSMutableURLRequest(URL: requestUrl!.URLByAppendingPathComponent(path))
            request.HTTPMethod = method

            let authHeader = userAuth ? Client.sharedInstance.userAuthHeader : Client.sharedInstance.clientAuthHeader
            request.setValue(authHeader, forHTTPHeaderField: "Authorization")

            let encoding = encoder
            let encodedRequest = encoding.encode(request, parameters: parameters).0
            return encodedRequest
        }
    }

The funny thing is, that the call with .Category works. Here's the code:

    func getCategory(categoryId:String, completion: (Category?, ErrorType?) -> Void) {
        let route = Router.Category(categoryId)
        let request = route.URLRequest
        let authHeader = request.valueForHTTPHeaderField("Authorization")
        NSLog("getCategory: \(request) - \(authHeader)")
        Alamofire.request(route)
            .responseObject { (category:Category?, meta:JoixesMetaData?, error: ErrorType?) -> Void in
                if error != nil || category == nil {
                    completion(nil, error)
                }
                else {
                    completion(category, nil)
                }
            }
    }

First request on the wire (Wireshark):

GET /api/v1/categories/_VWypVvLTnWSM7kcK2NuJAl_/? HTTP/1.1
Host: ****
Connection: keep-alive
Accept: */*
User-Agent: Joixes/com.joixes.Joixes (3; OS Version 9.0 (Build 13A340))
Accept-Language: en-US;q=1.0
Authorization: Basic Umctb25nQkxRYmF......
Accept-Encoding: gzip;q=1.0,compress;q=0.5

HTTP/1.0 200 OK
Date: Fri, 18 Sep 2015 17:01:54 GMT
Server: WSGIServer/0.2 CPython/3.4.3
Allow: GET, HEAD, OPTIONS
X-Frame-Options: SAMEORIGIN
Vary: Accept
Content-Type: application/json

{"data":{"uid":"_VWypVvLTnWSM7kcK2NuJAl_","name":"Clutches","longName":"Women, Clutches","parentCategory":"TF6thQUmTyiwJt10QsmLJgdC","verticalCategory":"x23Un1lcSGSTideM2RQdJw7N","isFindable":true,"hasChild":false,"childCategories":[]},"meta":{"detail":"Success.","code":200,"success":true}}

And with Criterias it does not work:

    func getCriteriasForCategory(categoryId:String, completion: ([BaseFilterCriteria], ErrorType?) -> Void) {
        let route = Router.Criterias(categoryId)
        let request = route.URLRequest
        let authHeader = request.valueForHTTPHeaderField("Authorization")
        NSLog("getCriteriasForCategory: \(request) - \(authHeader)")
        Alamofire.request(route)
            .responseJoixes { (jxResponse, error) -> Void in
                NSLog("getCriteriasForCategory: jxResponse: \(jxResponse)")
                var criterias:[BaseFilterCriteria] = []
                if let criteriaData = jxResponse?.data as? [AnyObject] {
                    criterias = criteriaData.map { return CriteriaFactory.parseCriteria($0 as! [String:AnyObject]) }
                }
                completion(criterias, error)
            }
    }

Note: The Authorization-Header in the variable authHeader is correct!! With both requests the exact same value

On the wire there is not :

GET /api/v1/categories/_VWypVvLTnWSM7kcK2NuJAl_/criteria/ HTTP/1.1
Host: *****
Accept-Language: en-US;q=1.0
User-Agent: Joixes/com.joixes.Joixes (3; OS Version 9.0 (Build 13A340))
Accept: */*
Accept-Encoding: gzip;q=1.0,compress;q=0.5
Connection: keep-alive

HTTP/1.0 401 UNAUTHORIZED
Date: Fri, 18 Sep 2015 17:02:03 GMT
Server: WSGIServer/0.2 CPython/3.4.3
Allow: GET, OPTIONS
WWW-Authenticate: Token realm=api
X-Frame-Options: SAMEORIGIN
Vary: Accept
Content-Type: application/json

{"data":null,"meta":{"detail":"Authentication credentials were not provided.","code":401,"success":false}}

Any Hints where the Header-Value could get lost??

Activity

pramodsharma403

pramodsharma403 commented on Sep 18, 2015

@pramodsharma403

@eburi Hi Please use this code to send Authorization-Header

let headers = [
            "Authorization": userData.userAPIKey!,
        ]
Alamofire.request(.GET, url, parameters: nil, encoding: .URL, headers: headers).response { (request, response, data, error) -> Void in
}
jaunesarmiento

jaunesarmiento commented on Sep 19, 2015

@jaunesarmiento

Had this same issue before updating to Xcode 7. I was running my app with Alamofire 1.3 on iOS 9 and authorization headers were not being received by my server. I did what @pramodsharma403 to fix/monkey-patch this issue.

I'd still want to set the headers with HTTPAdditionalHeaders though.

cnoon

cnoon commented on Sep 19, 2015

@cnoon
Member

Authorization headers should not be set in the HTTPAdditionalHeaders dictionary on the NSURLSessionConfiguration. Instead, an Authorization header should be appended to each individual request. This is the recommendation of both the ASF as well as Apple.

self-assigned this
on Sep 19, 2015
eburi

eburi commented on Sep 21, 2015

@eburi
Author

@pramodsharma403 How can I combine this with a Router? I have a lot of different requests and I would really like to use the router.

I implemented the URLRequestConvertible, I create a there an NSMutableURLRequest and I set the header on this request.

When you look at this code:

    func getCriteriasForCategory(categoryId:String, completion: ([BaseFilterCriteria], ErrorType?) -> Void) {
        let route = Router.Criterias(categoryId)
        let request = route.URLRequest
        let authHeader = request.valueForHTTPHeaderField("Authorization")
        NSLog("getCriteriasForCategory: \(request) - \(authHeader)")
        Alamofire.request(route)
            .responseJoixes { (jxResponse, error) -> Void in
                NSLog("getCriteriasForCategory: jxResponse: \(jxResponse)")
                var criterias:[BaseFilterCriteria] = []
                if let criteriaData = jxResponse?.data as? [AnyObject] {
                    criterias = criteriaData.map { return CriteriaFactory.parseCriteria($0 as! [String:AnyObject]) }
                }

                completion(criterias, error)
            }
    }

and this is the console output:

2015-09-21 16:56:03.318 Joixes[29243:7450013] getCriteriasForCategory: <NSMutableURLRequest: 0x7fa84ca05290> { URL: http://<REMOVED>/api/v1/categories/e4cN6UoyQSCAOBVh4R4BgAGY/criteria? } - Optional("Basic <REMOVED>")
2015-09-21 16:56:03.320 Joixes[29243:7450013] request: AuthHeader: Optional("Basic <REMOVED>")
2015-09-21 16:56:03.584 Joixes[29243:7450556] responseJoixes: data: Optional({
    data = "<null>";
    meta =     {
        code = 401;
        detail = "Authentication credentials were not provided.";
        success = 0;
    };
})

Note: I put where there is sensitive information (just a test-plattform anyway...)

I just don't understand this: How is the header not sent, when clearly present on the URLRequestConvertible. I also put a log message into public func request(URLRequest: URLRequestConvertible) -> Request in Alamofire/Manager.swift where it outputs basically the auth-header from the originalRequest-attribute on the DataTask. The value is still present there.

From my point of view, I'm giving to Alamofire the exact same thing as with any other request. With any other request it's just fine. But with this request, the Header is simply not sent.

I have no cloud what else could influence this....

cnoon

cnoon commented on Sep 21, 2015

@cnoon
Member

@eburi which version of Alamofire are you using? Alamofire 2.0.1 contains a fix that should solve this issue for you.

eburi

eburi commented on Sep 21, 2015

@eburi
Author

pod install says:

Using Alamofire (2.0.1)

But I just found out what the problem is, thanks to Wireshark! The request to the server does have the Authorization-Header set, but the server is replying with a 301 MOVED PERMANENTLY, and the subsequent request - I don't know who's doing this - is sent to the new location BUT without the headers from the original request! Hence the unauthorised response!

Since this "MOVED PERMANENTLY" is not visible to me as Alamofire-user, I was not aware of this.

It's actually very small change I missed in the API-Docs from the server I'm calling.
The endpoint used to be /criterias and it's now "MOVED" to /criterias/ ...

It would be great, if I would get a notice or Log-Message for 301 return-codes.
And it would be great if these Redirects were to be followed with the headers for the original request.

rolandoasmat

rolandoasmat commented on Apr 5, 2016

@rolandoasmat

@eburi So this was fixed by pointing to the correct endpoint and the Router worked accordingly?

phiberjenz

phiberjenz commented on Aug 4, 2016

@phiberjenz

I have the same problem. Trying to send a request with an Authorization header set on the NSMutableURLRequest. Header is visible on the request object in the completion handler, but not visible in the actual request sent to the server (no Authorization header when sending request through Charles Proxy). Any ideas?

simonnarang

simonnarang commented on Aug 4, 2016

@simonnarang

@phiberjenz The headers are sent in the URL body, not in the actual URL for a post request, in a get request, if you want them to show up in the actual URL you put them in the body parameter like you would in the headers parameter(as an array)

cnoon

cnoon commented on Aug 4, 2016

@cnoon
Member

@phiberjenz and @simonnarang: please refer to the info in #798 for more info on these findings. It walks you through the various options available to you when this happens.

Cheers. 🍻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @cnoon@eburi@jaunesarmiento@rolandoasmat@phiberjenz

      Issue actions

        Alamofire 2.0 Authorization-Header not sent iOS 9 · Issue #788 · Alamofire/Alamofire