Setting a Cookie in an Ajax Request

Can an AJAX response set a cookie?

Yes, you can set cookie in the AJAX request in the server-side code just as you'd do for a normal request since the server cannot differentiate between a normal request or an AJAX request.

AJAX requests are just a special way of requesting to server, the server will need to respond back as in any HTTP request. In the response of the request you can add cookies.

How to set cookie value with AJAX request?

Basically, ajax request as well as synchronous request sends your document cookies automatically. So, you need to set your cookie to document, not to request. However, your request is cross-domain, and things became more complicated. Basing on this answer, additionally to set document cookie, you should allow its sending to cross-domain environment:

type: "GET",    
url: "http://example.com",
cache: false,
// NO setCookies option available, set cookie to document
//setCookies: "lkfh89asdhjahska7al446dfg5kgfbfgdhfdbfgcvbcbc dfskljvdfhpl",
crossDomain: true,
dataType: 'json',
xhrFields: {
withCredentials: true
},
success: function (data) {
alert(data);
});

Why is the browser not setting cookies after an AJAX request returns?

OK, so I finally figured out the problem. It turns out that setting the Path option is important when sending cookies in an AJAX request. If you set Path=/, e.g.:

Set-Cookie:SessionId=foo; Path=/; HttpOnly

...then the browser will set the cookie when you navigate to a different page. Without setting Path, the browser uses the "default" path. Apparently, the default path for a cookie set by an AJAX request is different from the default path used when you navigate to a page directly. I'm using Go/Martini, so on the server-side I do this:

session.Options(session.Options{HttpOnly: true, Path:"/"})

I'd guess that Python/Ruby/etc. have a similar mechanism for setting Path.

See also: cookies problem in PHP and AJAX

Setting a cookie in an AJAX request?

Here are few suggestions:

  • Make sure that you are specifying the correct expiration format of date
  • When setting a cookie on a page that redirects, the cookie must be set after the call to header('Location: ....'); eg:

    header('Location: http://www.example.com/');
    setcookie('asite', $site, time()+60*60, '/', 'site.com');

  • If you have human urls like www.domain.com/path1/path2/, then you must set cookie path to / to work for all paths, not just current one.

    setcookie('type_id', $new_type_id, time() + 60*60*24*30, '/');

Notice the last / in the arguments.

From PHP manual:

The path on the server in which the
cookie will be available on. If set to
'/', the cookie will be available
within the entire domain . If set to
'/foo/', the cookie will only be
available within the /foo/ directory
and all sub-directories such as
/foo/bar/ of domain . The default
value is the current directory that
the cookie is being set in.

  • setcookie() defines a cookie to be sent along with the rest of the HTTP headers. Like other headers, cookies must be sent before any output from your script meaning there should be no html/code echo statements before that.

How to get a cookie from an AJAX response?

You're looking for a response header of Set-Cookie:

xhr.getResponseHeader('Set-Cookie');

It won't work with HTTPOnly cookies though.

Update

According to the XMLHttpRequest Level 1 and XMLHttpRequest Level 2, this particular response headers falls under the "forbidden" response headers that you can obtain using getResponseHeader(), so the only reason why this could work is basically a "naughty" browser.

unable to set cookie after ajax request

    $('form.login').submit(function(e) { 
$form = $(this);
e.preventDefault();
$.get('someUrl')
.done(function(data) { //data is returned async
setCookie('weirdName', data, 1); //use async called data
})
.fail(function() {
$('.error').show();
});
});

function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}

Cookies are not set from Cross domain AJAX request

Set the withCredentials

...
method : "POST",
xhrFields: {
withCredentials: true
},
...

AJAX request not sending cookies (NET 5)

I quite like the style of what you are doing here in terms of an SPA getting cookies from an API. Some recommendations below, based on experience at dealing with these issues.

PROBLEM

You are calling from the browser to an API in a different domain, meaning the cookie is third party and modern browsers will drop it aggressively.

  • Web Origin: localhost:44316
  • API Domain: myazurewebapp.com

SameSite=None is the theoretical solution from standards docs but these often do not explain current browser behaviour:

  • You have to set the Secure property, as Jason Pan says
  • But it will still not work in the Safari browser and maybe some others
  • Expect cross site cookies to be dropped in all browsers in the near future

SOLUTION

The preferred option is to design hosting domains so that only first party cookies are used, and many software companies have done this. It can be done by running the API in a child or sibling domain of the web origin:

  • Web Origin: www.example.com
  • API Domain: api.example.com

On a developer PC you can do this simply by updating your hosts file. Note also that you can run web and API components on different ports and they will remain same site:

127.0.0.1 localhost www.example.com api.example.com
:1 localhost

The browser will then still be making CORS requests, but will consider the cookie issued by the API to be in the same site as the web origin. You can then also change the cookie settings to use SameSite=strict, for best security.

FURTHER INFO

At Curity we have published some recent articles on web security that are closely related to your question, since secure cookies used in OpenID Connect security have also had to deal with dropped cookie problems:

  • Code
  • Articles


Related Topics



Leave a reply



Submit