JohnB
JohnB

Reputation: 59

Error 401 on WEB API 2 when there is lot of request from Android device

I’m developing an Android App and a Web Service that communicate. My Web Service is in WEB API 2 with token bearer authentication.

My problem is that when I send too many requests (~20 request in 15 seconds) to my Web Service from my Android App, the WS response with

    “401” : “Authorization has been denied for this request”

This happen ONLY on the production server (Amen hoster) AND from the Android Device. For example, if I try with Postman, everything works fine. So it’s related to my production server and/or my android app request.

The code for access to the Web Service

    URL obj = new URL(SERVEUR_URL + url);
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();
    con.setRequestMethod("GET");
    con.setRequestProperty("Authorization", "Bearer " + token);
    con.setRequestProperty("Content-Type", "application/json");

    int responseCode = con.getResponseCode();
    String responseMessage = con.getResponseMessage();

The authentication provider on my Web Service is the default one. No modifications.

The request from my Android App (not work every time)

    GET http://api.xxxx.com/api/Weesps/GetAvailableWeesps HTTP/1.1
    Authorization: Bearer XXXX
    Content-Type: application/json
    User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0; Google Nexus 5X - 6.0.0 - API 23 - 1080x1920 Build/MRA58K)
    Host: api.xxxx.com
    Connection: Keep-Alive
    Accept-Encoding: gzip

The request from Postman (work every time)

    GET http://api.xxxx.com/api/Weesps/GetAvailableWeesps HTTP/1.1
    Host: api.xxxx.com
    Connection: keep-alive
    Authorization: Bearer XXXX
    Cache-Control: no-cache
    User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36         (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
    Postman-Token: bca55154-775d-9709-7a8b-4793393890ad
    Accept: */*
    Accept-Encoding: gzip, deflate, sdch
    Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
    Cookie: dadaproaffinity=14ff51cc869a14d3552485cb4ceee1faa1be7165cc5d4b0e2b19370f11afcbea

What I have tried:

I spend two days on this problem and read many stackoverflow posts but no one helps me. Thanks for your help.

UPDATE 1 :

With Fiddler I saw that in GET request from Postman, they were a Cookie header. This cookie is sent when we ask for a bearer token.

Example of token response from the server

    HTTP/1.1 200 OK
    Cache-Control: no-cache
    Pragma: no-cache
    Content-Length: 691
    Content-Type: application/json;charset=UTF-8
    Expires: -1
    Server: Microsoft-IIS/8.5
    Set-Cookie: .AspNet.Cookies=XXXX; path=/; HttpOnly
    X-Powered-By: ASP.NET
    X-Powered-By: ARR/2.5
    Date: Tue, 31 May 2016 16:55:39 GMT

            {"access_token":"XXXX","token_type":"bearer","expires_in":1209599,"userName":"Foo",".issued":"Tue, 31 May 2016 16:55:40 GMT",".expires":"Tue, 14 Jun 2016 16:55:40 GMT"}

Fiddler and Postman saved this cookie and they automatically put it in requests to API (example on the “The request from Postman” code block). When I remove the cookie from the Postman GET request, it doesn’t work (just like my android app).

Now, the question is: why WEB API 2 send a cookie instead of only using the token ? And why the token work great in the first requests and don’t work properly for the following requests ?

Upvotes: 1

Views: 2355

Answers (2)

JohnB
JohnB

Reputation: 59

Finally, I got my answer:

My Web Service send a Cookie named “dadaproaffinity” the first time I ask for a request. This Cookie was automatically put on the following request by Postman but not by Android HttpUrlConnection. So, I just take this Cookie and now I just add this Cookie on every requests with the Token.

But : This cookie is send by IIS, not by my Web Service ! That’s why it works on local but not on the production server. I googled this cookie and there are very few responses about that. The only one that I find in English is :

    Technical Cookie of IIS Server hosting the site.
    Need to route to the correct server session, in order to keep it active

Does anyone have more information about this IIS Cookie ?

Upvotes: 0

RynnHeldeD
RynnHeldeD

Reputation: 51

According to ASP.NET WebAPI2 flow you can see on the bottom of that page, it seems your requests are always authenticated but sometimes fail to get authorized.

So imo, the AuthorizationFilter[Authorize] rejects some of your requests for an unknown reason. What I would suggest is to dump the request your API receives as well as the claims identity attached to the token. Try to see if there is differences between them when you have a successful response and when you have a 401.

That way, you may be able to determine either it is your request that got malformed, if it is the claims identity that is not good or if it is the AuthorizationFilter that refuses you for another reason (like too much queries or else).

Good luck !

UPDATE 1 According to your new input, I think that your Web API is configured to use both token and cookie authentication.

What I see here is you have two solutions : 1°/ Store the returned cookie in your Android application and use it for next calls. Simplest and fastest way to solve your problem without changing all your API, but you store an authorization cookie : it can leads to security problem (CSRF attacks).

2°/ You can check how your authentication and authorization filters are set to disable cookie authentication and only rely on token authentication : it will hence forces all the requests and your API to only use token and will prevents you from suffering CSRF attacks. More complex because you have to dig into your web API configuration.

Check the following links (sorry, as I don't have enough reputation yet to post more than 2 links per post, you'll find them as text at the end of my answer) :

  • ASP.net Secure a Web API 2.2[2] : From the chapter "Configuring the Authorization Server" at the bottom
  • MSDN article on Web API security[3] : More general and technical information about web api security, how to secure it and CRSF attacks

  • StackOverflow .NET cookie and token authentication[4] : Check David Banister's answer, I think it is exactly what you want to do : Only use token for all your API calls.

  • StackOverflow Authorize filter and authentication[5] : More information about such mechanisms for your API

And finally

  • Cookie authentication with web API and 401 codes[6] : Sounds like your actual problem, isn't it ?

I hope it helps you, good luck !

// Links

2: www.asp.net/web-api/overview/security/individual-accounts-in-web-api

3: msdn.microsoft.com/en-us/magazine/dn201748.aspx

4: stackoverflow.com/questions/22568409/mvc-net-cookie-authenticated-system-acessing-a-web-api-with-token-authenticatio

5: stackoverflow.com/questions/21231751/authorize-filter-and-authentication

6: brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/

Upvotes: 1

Related Questions