Web Browser Does Not Set cookie on an Ajax Call - javascript

I'm very confused. I've got an AJAX call which causes a login form to be processed, and creates a cookie on a successful login. The web browser is not registering the cookie.
In troubleshooting, I isolated it down to something to do with the AJAX calling the site, rather than navigating directly.
e.g. I created a simple page "test" which returns the following output:
HTTP/1.1 200 OK
X-Powered-By: Express
Set-Cookie: token=ABCDEFG; Domain=localhost; Path=/
Content-Type: application/json; charset=utf-8
Content-Length: 19
ETag: W/"13-S4werj8PuppRlonJZs+jKA"
Date: Wed, 23 Sep 2015 22:09:03 GMT
Connection: keep-alive
{"message":"value"}
If I navigate directly to the page, the cookie is created in the browser.
If I make an AJAX call to the page, the cookie is not created in the browser.
e.g:
$.get('http://localhost:8081/test');
I've found similar posts which state that this happens with AJAX if the domain or the path are not defined, but as you can see, I defined these and still no dice.
If it matters, the majority of my testing has been on Firefox, but I did do at least a couple of tests on Chrome.
Any help you have would greatly be appreciated. I'm confused by this, as everything I read suggests this should be possible.
To clarify further:
1) I'm not seeing the cookie created when reviewing CookieManager+ addon for Firefox.
2) I'm also not seeing the cookie added to subsequent requests to the same host (even the same port).
3) What I read seems to suggest that cookies are tied to a host, not a port (But that doesn't seem to be the issue based on #1 and #2):
Are HTTP cookies port specific?

Try setting withCredentials in your request:
$.get('http://localhost:8081/test', {xhrFields: {withCredentials: true}});
Alternatively try setting the crossDomain value:
$.ajax({type:"GET", url:"localhost:8081/test", crossDomain:true});

If you're trying to do this in Angular, as I was, this is how you do it there:
$http doesn't send cookie in Requests
config(function ($httpProvider) {
$httpProvider.defaults.withCredentials = true;

Related

Firefox combining 'Connection: keep-alive, Upgrade' conflicts with mobile operator proxy

I have a WebSocketServer running on a server box, with a website attempting to connect to it and send back and forth information.
I have noticed that on WiFi it works perfectly on all the browsers I have tested, however over Mobile Data Firefox. I intercepted and edited headers and managed to reproduce the problem. Firefox is sending a combined header Connection: keep-alive, Upgrade in the request. Chrome in comparison is just sending Connection: Upgrade. My theory is that when the request passes through the mobile data provider's proxy, as well as adding their own identifying headers, it re-parses all of the other headers, and does not understand a combined header. This is confirmed by the fact that at the server end, the request is received (from Firefox) but the Connection header is truncated to Connection: keep-alive. If I manually remove the keep-alive from the Connection header using the interception program, the problem is solved.
I don't need the keep-alive part of the request (in fact if anything I would prefer it not to be enabled) so I'm asking if there is a way to stop Firefox sending it without using about:config etc (e.g. in JS or HTML), as I would like for this to work for the general end-user.
Many thanks,
Richard
I had a similar problem, henceforth resolved.
In my case, the problem was that my hosting provider had a proxy which was not dealing correctly with the Connection and/or Upgrade headers. Indeed, these headers are hop-by-hop and as such:
Hop-by-hop headers
are meaningful only for a single transport-level connection and must not be retransmitted by proxies or cached. Such headers are: Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, TE, Trailer, Transfer-Encoding and Upgrade. Note that only hop-by-hop headers may be set using the Connection general header.
Souce: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
Shortly, these headers are not retransmitted but somehow interpreted before being passed to your server. When these headers are sent by Firefox, this phase of interpretation becomes critical since the value associated to the Connection header is more "complicated" than that sent by other browsers, i.e.
Firefox sends Connection: keep-alive, Upgrade
Chrome/Edge/... sends Connection: Upgrade
Solution : I simply told my hosting provider that only Connection: keep alive arrives to my server when one sends Upgrade: <my_protocole> AND Connection: keep alive, Upgrade (and he had the possibility to correct the issu within 72 hours).

Set-Cookie in Response Header not being set in browser

I am having issues with trying to set a cookie from a Response Header, I can see the set-cookie key with all the options that i have specified but for some reason it is not being set in the browser (Chrome).
I am setting the cookie using koajs, and reads as follows:
this.cookies.set(’test-cookie’, ‘valid’, { domain: ‘.test.io’, httpOnly: false, maxAge: 604800000 })
this is what I get in the response:
GET https://api.test.io/conversion
set-cookie: test-cookie=valid; path=/; expires=Mon, 12 Jun 2017 14:23:40 GMT; domain=.test.io;
I have another request (GET https://identity.test.io/identity) that does a similar request and has the same set-cookie response and i can see this cookie in chrome dev tools.
The only difference is api.test.io goes through several redirects (301), however we do not think that is the issue as we still see the set-cookie key in the final response header.
nb: this cookie needs to work across multiple sites which is why we don’t set secure, signed or httpOnly.
My answer is strictly for local testing, but I am putting it here as an answer cause your question is exactly what I searched for before I fixed it.
My php.ini file had the session.auto_start setting set to 0. I set it to 1, and the browser started saving cookies that were in response header. (using WAMP with PHP 7.0.29)

Using Parse Client Key in Angular gives CORS error

I am attempting to retrieve a class (with GET) from Parse using a client key. I was able to send a successful request using Advanced Rest Client for Google Chrome; I used X-Parse-Application-Id and X-Parse-Client-Key headers.
[edit] [edit2]
Response headers (obtained from Chrome Developer Tools OPTIONS):
HTTP/1.1 200 OK
Access-Control-Allow-Headers: X-Parse-REST-API-Key, X-Parse-Javascript-Key, X-Parse-Application-Id, X-Parse-Client-Version, X-Parse-Session-Token, X-Requested-With, X-Parse-Revocable-Session, Content-Type
Access-Control-Allow-Methods: OPTIONS, POST, GET, PUT, DELETE
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 86400
Content-Type: application/json; charset=utf-8
Date: Sun, 29 Nov 2015 04:23:08 GMT
Server: nginx/1.6.0
X-Parse-Platform: G1
X-Runtime: 0.000118
Content-Length: 0
Connection: keep-alive
However, attempting to do the same in an Angular app gives me the following error:
XMLHttpRequest cannot load https://api.parse.com/1/classes/GenResources. Request header field X-Parse-Client-Key is not allowed by Access-Control-Allow-Headers in preflight response.
Parse says it supports using cross-origin resource sharing, and I was able to make the request earlier using a different client so I'm pretty sure the server isn't the issue. I wouldn't be able to modify what the response header is anyways.
Here's the code I used to form the GET request.
var ng_portal = angular.module("ngPortal", []);
ng_portal.controller("GenResourcesCtrl", ["$http", function($http) {
$http({
method: "GET",
url: PARSE_URL + "/1/classes/GenResources",
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": PARSE_APP_ID,
"X-Parse-Client-Key": PARSE_CLIENT_KEY
}
}).then(
function success(res) {
console.log(res);
},
function error(res) {
console.log(res);
}
);
}]);
You are setting custom headers in the request, which will trigger a pre-flight (OPTIONS) request. The response from that request must include a header called "access-control-allow-headers" with the value being a list of the headers you are trying to set.
See https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
specifically the section on pre-flight requests.
I suggest using the browser developer tools to look at the headers of the requests and responses to see if they conform to the CORS spec. From the error message you provided, it looks like the server hosting the cross domain call you are making, does not support custom headers. If you see otherwise, please update your question with the headers and I can provide more help.
This seems to be an issue with Parse.com actually. After exactly one frustrated hour, I came across this Google Groups post
Relevant quote
From my testing, this never ( client or javascript key) worked via javascript rest interactions through the browser.
I actually created a Parse Bug on this:
https://developers.facebook.com/bugs/488204124680438
Because I thought both of those keys should work through the browser ( WITHOUT NEEDING TO USE A SDK ).
I’d suggest reading reading my bug. I still think the the correct implementation is to enable these keys to work properly with browser requests because it works if you do it outside the browser.
But alas, they don’t seem to get the issue, or don’t understand why disabling it only in the browser doesn’t make sense since you can use it on any other platform without issues. Just… Doesn’t… Make… Sense.
I instead used my JavaScript Key X-Parse-Javascript-Key (which, according to the docs as of today, only works with their JavaScript SDK) and it works fine as a drop-in replacement for X-Parse-Client-Key

intercept response header with jquery ajax request

Exactly what the title suggests:
I perform an ajax request to my server, it responds with a 403 but there are headers I want to retrieve and save on localStorage. This is for a phonegap app (Android and iOS), so the initiating domain isLocal (file://). When performing the call, I use the following code to try to intercept the response, but it returns undefined or an empty string.
Ajax:
$.ajax({
url: serverLink+action,
type: "POST",
data: "access_token="+accessToken+"&uid="+uid,
crossDomain: true,
complete: function(resp){
var header = resp.getAllResponseHeaders();
var match = header.match(/(Set-Cookie|set-cookie): (.+?);/);
if (match) session = match[2];
console.log(header, session)
}
})
Response Headers
Connection Keep-Alive
Content-Encoding gzip
Content-Length 1198
Content-Type text/html
Date Fri, 13 Apr 2012 22:51:02 GMT
Keep-Alive timeout=15, max=100
Server Apache/2.2.14 (Ubuntu)
Set-Cookie sessionid=ebd26167e32bada2d2ed0bd3cc16d8a2; expires=Fri, 27-Apr-2012 22:51:02 GMT; Max-Age=1209600; Path=/
Vary Cookie,Accept-Encoding
Further reading led me to here, which speaks of the CSRF on a django server. We are using a django server and either this or the 403 is the problem I suspect. There doesn't seem to be a way (from the example answer there) to collect the cookie from webview and send it back to the server on subsequent requests.
use the jquery XHR object which as a method getAllResponseHeaders() which should provide what you are after.
http://api.jquery.com/jQuery.ajax/
This problem was most definitely caused by CSRF protection on the django server. Disabling or implementing workarounds as per django is the only way around this.
Actually this post helped tremendously: Django CSRF check failing with an Ajax POST request

Firefox 3 not using cache when ajax call made during page load

I get some json data with ajax when the page DOM is loaded using jQuery like this:
$(document).ready(function(){
getData();
});
...where getData() is a simple jQuery ajax call, something like this:
function getData(){
$.ajax({cache: true, dataType: 'json', url: '/foo/bar'});
}
The Expires header for this request is set to some time in the future, so the next time I load the page, the ajax call should use the cached data. Firefox 3 does not.
But, if I instead ask for the data like this:
$(document).ready(function(){
setTimeout("getData()", 1);
});
Firefox does respect the Expires header, and uses the cache. Any ideas why this would be?
This page mentions that browsers may treat ajax calls that occur when a page loads differently from ajax calls that occur in response to a user UI event.
Edit: I forgot to include the http headers in my original post. I think the headers are fine, because the caching works as long as the request isn't made in an ajax call when the page loads. If I visit the url that the ajax call uses in my browser URL bar, caching works, and as I explain above, caching works if I add a little delay to the ajax call.
Request headers
Host 10.0.45.64:5004
User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.9) Gecko/20100824 Firefox/3.6.9
Accept application/json, text/javascript, /
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
X-Requested-With XMLHttpRequest
Cookie
Response headers
I set the Expires header to 1 week in the future so that users only need to refresh once a week.
Date Wed, 04 May 2011 15:32:04 GMT
Last-Modified Wed, 04 May 2011 15:32:03 GMT
Expires Wed, 11 May 2011 15:32:03 GMT
Content-Type text/javascript
Cache-Control Public
Connection close
Define an error handler in the $.ajax() call and inspect the response headers (using jqXHR.getAllResponseHeaders() where jqXHR is the jQuery Ajax object, status code, and responseText.length. You may find that the request is successful, but jQuery treats them as unsuccessful. I've recently had a similar issue with cached files and $.ajax(), and it turns out that sometimes when files are loaded when the browser is offline, or from a local file, return a status code of 0. Because the status doesn't fall in the range of success codes (200-300), jQuery considers the request to have failed. See this for what I did to fix this issue. Basically, in your error handler, you can check the responseText.length. If it is non-empty, consider the request successful and parse the JSON using JSON.parse(). BUT!!! you have to make sure on your server-side that invalid requests are empty.

Categories