AngularJS $http POST withCredentials fails with data in request body

Amir Jamak picture Amir Jamak · Mar 13, 2014 · Viewed 10.2k times · Source

AngularJS authenticates against server side using REST, and gets the JSESSIONID cookie. In the next step I am trying to get some JSON data from server side using REST along with the session cookie gained in the previous step. Here is the client-side code:

getSomeJSONDataFromServer:function() {
var deferred = $q.defer();
$http({
    method: 'POST',
    withCredentials: true,
    url: "http://domain.name/app/someURL",
    headers:{
        'Accept':'application/json',
        'Content-Type':'application/json; charset=utf-8',
        'Access-Control-Request-Headers': 'X-Requested-With, content-type, accept, origin, withcredentials'
    }
})
.success(function(data, status, headers, config) {
    // handle data
})
.error(function(data, status, headers, config) {
    // handle error
});
return deferred.promise;
}

The code above works OK:

CORS $http request without body

The problems start when I send some data in the above POST request body.

...
$http({
    method: 'POST',
    withCredentials: true,
    url: "http://domain.name/app/someURL",
    headers:{
        'Accept':'application/json',
        'Content-Type':'application/json; charset=utf-8',
        'Access-Control-Request-Headers': 'X-Requested-With, content-type, accept, origin, withcredentials'
    },
    data: '{}'
})
.success(...

The above code fails in the prelight request:

CORS $http request with body fails!

Looks like the server starts a new session because the session cookie is not sent for some reason. Anyway, I feel like I am missing something really simple, some header or something like that... Any ideas are appreciated. Thanks in advance.

Answer

mxcgi picture mxcgi · Aug 11, 2014

Amir,

Allow me to help you and others clearly understand what is expected when dealing with CORS, as such:

Index:

  • Simple CORS Version
  • Preflighted CORS version
  • Requests with Credentials

Simple CORS Version

  1. You can use GET, HEAD or POST:
    • In any of the method cases, you CANNOT set custom headers.
    • You can always have the server side restrict domain access through Access-Control-Allow-Origin header.
  2. And if POST has request data:
    • Content-Type MUST BE either of the followings:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/html

This SIMPLE version clearly IS NOT your case...

Preflighted CORS Version

  1. You can use GET, HEAD or POST:
    • In any of the method cases, you CAN set custom headers.
    • You can always have the server side restrict domain access through Access-Control-Allow-Origin header.
  2. And if POST has request data:
    • Content-Type MAY BE of the followings:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/html
    • Content-Type CAN ALSO BE of other types:
      • application/json
      • application/xml
      • text/xml
      • etc.

This PREFLIGHTED version clearly IS your case...

Requests with Credentials

  1. If your invoking calls with cookies, you need to set the following parameter part of your request:
    • withCredentials = true

Requests with Credentials clearly IS your case as well...