Normal to see Status 204 then Status 200? - ajax

I am looking at my ajax request in network tab in chrome and I noticed every ajax request I do happens twice.
First one is a 204 and then followed up with 200. My ajax call is only being hit once so I am not sure why there are 2.
Edit
So it seems to have to do with Cors, which I have just set to star (*) for testing.
I guess there is not to much I can do to not have it do 2 requests, but what really gets me is why it takes so long, I looking at google chrome network and on my page these 204 took anywhere from 110ms to 1.97 seconds.

That's a consequence of the CORS - Cross-origin resource sharing "protocol".
When doing requests do other domains, the browser do a request before your request, asking for the server if it can proceed with that request.
This request uses the method OPTIONS and should have no content, just response headers, that's why the response code is 204 (no content). After confirming that the request is allowed, the browser proceed with your request, that now will return 200 (or any other) status code.

When you try to send a AJAX request to a different domain, you are violating the same-origin policy.
Server that you are sending the request allows cross domain requests. In the process, there should be a preflight call and that is the HTTP OPTION call.
So, you are having two responses for the OPTION and your result.

Related

Chrome firing two OPTIONS requests on CORS preflight

When doing CORS requests that require preflight, they fail to work on our network. Instead of Chrome making two requests, the OPTIONS and PUT, it fires two OPTIONS requests that are exactly the same, this ends up in the following error:
XMLHttpRequest cannot load http://server/api/foo. Response for preflight is invalid (redirect)
Digging into the problem, there are two things that stand out.
If I turn on Throttling in the Network section of the Chrome developer tools, things work and the OPTIONS request is followed by a PUT.
Under the timing tab, it almost looks like as if it tries to fire both (First request,
Second request) requests simultaneously. Despite the fact that a request is queued at a later time, the Started At time shows it at the same request as the initial OPTIONS request.
The throttled working, and non-working requests look fairly similar for comparison.

Do browsers allow cross-domain requests to be "sent"?

I am newbie to website security and currently trying to understand Same-Origin-Policy in some depth.
While there are very good posts on stackoverflow and elsewhere about the concept of SOP, I could not find updated information on whether chrome and other browsers allow cross-domain XHR post requests to be 'sent' from the first place.
From this 5 year old post, it appears that chrome allows the request to pass through to the requested server but does not allow reading the response by the requester.
I tested that on my website trying to change user info on my server from a different domain. Details below:
My domain: "www.mysite.com"
Attacker domain: "www.attacker.mysite.com"
According to Same-Origin-Policy those two are considered different Origins.
User (while logged in to www.mysite.com) opens www.attacker.mysite.com and presses a button that fires a POST request to 'www.mysite.com' server...The submitted hidden form (without tokens in this case) has all the required information to change the user's info on 'www.mysite.com' server --> Result: CSRF successful attack: The user info does indeed change.
Now do the same but with javascript submitting the form through JQuery .post instead of submitting the form--> Result: Besides chrome giving the normal response:
No 'Access-Control-Allow-Origin' header is present on the requested
resource
, I found that no change is done on the server side...It seems that the request does not even pass through from the browser. The user info does not change at all! While that sounds good, I was expecting the opposite.
According to my understanding and the post linked above, for cross-domain requests, only the server response should be blocked by the browser not sending the post request to the server from the first place.
Also, I do not have any CORS configuration set; no Access-Control-Allow-Origin headers are sent. But even if I had that set, that should apply only on 'reading' the server response not actually sending the request...right?
I thought of preflights, where a request is sent to check if it's allowed on the server or not, and thus blocking the request before sending its actual data to change the user info. However, according to Access_Control_CORS , those preflights are only sent in specific situations which do not apply to my simple AJAX post request (which includes a simple form with enctype by default application/x-www-form-urlencoded and no custom headers are sent).
So is it that chrome has changed its security specs to prevent the post request to a cross domain from the first place?
or am I missing something here in my understanding to the same-origin-policy?
Either way, it would be helpful to know if there is a source for updated security measures implemented in different web browsers.
The XMLHttpRequest object behavior has been revisited with time.
The first AJAX request were unconstrained.
When SOP was introduced the XMLHttpRequest was updated to restrict every cross-origin request
If the origin of url is not same origin with the XMLHttpRequest origin the user agent should raise a SECURITY_ERR exception and terminate these steps.
From XMLHttpRequest Level 1, open method
The idea was that an AJAX request that couldn't read the response was useless and probably malicious, so they were forbidden.
So in general a cross-origin AJAX call would never make it to the server.
This API is now called XMLHttpRequest Level 1.
It turned out that SOP was in general too strict, before CORS was developed, Microsoft started to supply (and tried to standardize) a new XMLHttpRequest2 API that would allow only some specific requests, stripped by any cookie and most headers.
The standardization failed and was merged back into the XMLHttpRequest API after the advent of CORS. The behavior of Microsoft API was mostly retained but more complex (read: potentially dangerous) requests were allowed upon specific allowance from the server (through the use of pre-flights).
A POST request with non simple headers or Content-Type is considered complex, so it requires a pre-flight.
Pre-flights are done with the OPTIONS method and doesn't contain any form information, as such no updates on the server are done.
When the pre-flight fails, the user-agent (the browser) terminate the AJAX request, preserving the XMLHttpRequest Level 1 behavior.
So in short: For XMLHttpRequest the SOP was stronger, deny any cross-origin operations despite the goals stated by the SOP principles. This was possible because at the time that didn't break anything.
CORS loosened the policy allowing "non harmful" requests by default and allowing the negotiation of the others.
OK...I got it...It's neither a new policy in chrome nor missing something in SOP...
The session cookies of "www.mysite.com" were set to "HttpOnly" which means, as mentioned here, that they won't be sent along with AJAX requests, and thus the server won't change the user's details in point (4).
Once I added xhrFields: { withCredentials:true } to my post request, I was able to change the user's information in a cross-domain XHR POST call as expected.
Although this proves the already known fact that the browser actually sends the cross-domain post requests to the server and only blocks the server response, it might still be helpful to those trying to deepen their understanding to SOP and/or playing with CORS.

Response Data for "GET Method"

I am creating different HTTP Requests for a site and taking an access token as a variable from Regular Expression Extractor and using it in another HTTP Request.
The Thread group is working fine; i.e. no error in View Results Tree. But Response data is only coming for the Request with POST Method. Nothing is coming for the Request with GET Method and both requests are taking the access token properly.
In some cases you may get response code 200 ok and request still may fail. In case of your get request that seems to be happening.
Check following:
Headers being sent with get request. (Compare request being sent from JMeter and from real browser.)
Add response assertion to get request to be assure the correctness of the response. (Check what response you get for the request made from browser.)
Make sure you have added cookie manager in the test plan.

Does a server have to carry out an operation before redirection?

In Is HTTP 303 acceptable for other HTTP methods? we established that HTTP 303 can be used for other HTTP methods.
The Post/Redirect/Get pattern requires the server to carry out an operation before returning HTTP 303. Is the same true for HTTP PUT and DELETE for this and other types of redirects? Is the server required to carry out the operation before redirection? Or can it assume that the client will repeat the request on the canonical URL as necessary?
This becomes even more interesting when you consider the fact that redirection is often used for load-balancing.
Quoting RESTful Web Services page 378:
303 ("See Other")
The request has been processed, but instead of the server sending a response document,
it’s sending the client the URI of a response document. This may be the URI to a static
status message, or the URI to some more interesting resource.
A few pages later...
307 (“Temporary Redirect”)
The request has not been processed, because the requested resource is not home: it’s
located at some other URI. The client should resubmit the request to another URI.
For GET requests, where the only thing being requested is that the server send a representation, this status code is identical to 303 (“See Other”). A typical case where 307 is a good response to a GET is when the server wants to send a client to a mirror site. But for POST, PUT, and DELETE requests, where the server is expected to take some
action in response to the request, this status code is significantly different from 303.
A 303 in response to a POST, PUT, or DELETE means that the operation has succeeded
but that the response entity-body is not being sent along with this request. If the client
wants the response entity-body, it needs to make a GET request to another URI.
A 307 in response to a POST, PUT, or DELETE means that the server has not even tried
to perform the operation. The client needs to resubmit the entire request to the URI in
the Location header.
An analogy may help. You go to a pharmacy with a prescription to be filled. A 303 is
the pharmacist saying “We’ve filled your prescription. Go to the next window to pick
up your medicine.” A 307 is the pharmacist saying “We can’t fill that prescription. Go
to the pharmacy next door.”

Who blocks cross domain AJAX request browser or webserver or both?

Cross domain AJAX requests are reported as "aborted" in firebug. I know this is supposed to be security feature but where exactly these requests get rejected ? At the browser end or at the server end ?
Browser - they don't get sent at all. If you check your HTTP traffic (e.g. using Fiddler), you'll see that there is no corresponding HTTP request initiated for those aborted AJAX requests.
(That is also the only place where such blocking makes sense, as the server doesn't have a reliable way to distinguish between AJAX requests and normal requests; only the browser has enough context to make such decision.)

Resources