androidhttphttp-headersodataandroidhttpclient

x-csrf-token validation fails on HttpPost


I have to post xml payload to an ODATA service which requires Authentication and x-csrf-token.

I have two AsyncTasks. In First one has URLConnection object and fetches x-csrf-token with code below:

 URL obj = new URL(Util.ODATA_URL + "SO_BEATPSet");
                    URLConnection conn = obj.openConnection();
                    conn.setRequestProperty("Authorization", "Basic " + authStringEnc);
                    conn.addRequestProperty("x-csrf-token", "fetch");

......
......

 String server = conn.getHeaderField("x-csrf-token");

Now, in Second AsyncTask executed right after the first one finishes succesfully, i encounter 403 error. It bascially says that my x-csrf-token validation has failed.

I ran a simple looping test, where i ran the first AsyncTask three times, and i got three different tokens. That is where i think the problem is. When in Second AsyncTask I use HttpPost, the server is expecting a different token other than an already fetched one.

Is there any way that i can fetch and pass the X-csrf-token in the same call? My Second AsyncTask is like below:

HttpPost postRequest = new HttpPost(url);

String credentials = UUSERNAME + ":" + PASSWORD;
                    String base64EncodedCredentials = Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);

postRequest.addHeader("Authorization", "Basic " + base64EncodedCredentials);
postRequest.addHeader("x-csrf-token", X_CSRF_TOKEN); //   JHc4mG8siXrDtMSx0eD9wQ==

StringEntity entity = new StringEntity(XMLBuilders.BeatXMLBuilder());
entity.setContentType(new BasicHeader("Content-Type",
                            "application/atom+xml"));
postRequest.setEntity(entity);

Solution

  • I was eventually able to get the successful POST result. However, the solution seems a bit dirty to me. But, it did sort out my problem for now.

    I put the Code like below in doInBackground() method of AsyncTask

     HttpClient httpclient = new DefaultHttpClient();
     HttpPost postRequest = new HttpPost(url);
    
     String credentials = USERNAME + ":" +PASSWORD;
     String base64EncodedCredentials = Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
    
      /**---------------------------------------------------------------------------------- **/
      /** THIS CODE BELOW CALLS THE SERVER FOR THE TOKEN AND PASSES THE VALUE TO THE SUBSEQUENT POSTREQUEST CALL.
          BY DOING THIS, THE SERVER IS NOT CALLED AGAIN BEFORE POSTREQUEST, AND USER GETS THE LATEST TOKEN **/
                            {
                                HttpGet httpget = new HttpGet(url);
                                httpget.setHeader("Authorization", "Basic " + base64EncodedCredentials);
                                httpget.setHeader("x-csrf-token", "fetch");
    
                                System.out.println("request:-------------------");
                                System.out.println(httpget.getRequestLine());
                                Header headers[] = httpget.getAllHeaders();
                                for (Header h : headers) {
                                    System.out.println(h.getName() + "---:---- " + h.getValue());
                                }
    
                                HttpResponse res = httpclient.execute(httpget);                           
                                System.out.println("response:-------------------");
                                System.out.println(res.getStatusLine());
    
                                headers = res.getAllHeaders();
                                for (Header h : headers) {
                                    System.out.println(h.getName() + "---:---- " + h.getValue());
                                    if (h.getName().equals("x-csrf-token")) {
                                        X_CSRF_TOKEN = h.getValue();
                                    }
                                }
                            }
      /**--------------------------------------------------------------------- **/
    
    
        // The main POST REQUEST
         postRequest.addHeader("Authorization", "Basic " + base64EncodedCredentials);
         postRequest.setHeader("x-csrf-token", X_CSRF_TOKEN); //   PASSING THE TOKEN GOTTEN FROM THE CODE ABOVE
    
    
         StringEntity entity = new StringEntity(myString);
         entity.setContentType(new BasicHeader("Content-Type",
                                    "application/atom+xml"));
         postRequest.setEntity(entity);
    
    
         HttpResponse response = httpclient.execute(postRequest);
         Log.d("Http Post Response:", response.toString());
    
         String result = EntityUtils.toString(response.getEntity());
         Log.d("Http Response:", result);
    
         int responseCode = response.getStatusLine().getStatusCode();
         Log.d("Http Response: ", "Response code " + responseCode);
    

    As I explain in the Code comments as well, the Code makes another call to the server while HttpPost has already made one and gets the latest token, which in turn is passed to the subsequent POST request.