Bram Vanroy Bram Vanroy - 2 months ago 16
Ajax Question

First setting a SESSION variable through ajax, and the using it upon visiting page

I want to POST a string across domains by using AJAX and CORS after a mouse click, and when the POST is successful use that string as a SESSION variable. When ajax fires the done() event, I then want to open a new tab to the domain we posted to earlier and use the SESSION variable.

What I want to achieve, summarised




  • a user is on site A

  • site A does a POST request to page A on site B where it wants to post a string to

  • page A on site B stores the string in a SESSION variable

  • upon success the browser opens a new tab to page B on site B

  • page B on site B looks for the SESSION variable and uses it if present



Even though I was initially planning on solving this with a SharedWorker support does not seem to be quite right for it. Just using a URL parameter / a GET is not possible either because I fear that the size of the data can get too long.

What I have



php/receive-post.php
on domain B

<?php
$origin = $_SERVER['HTTP_ORIGIN'];

if ($origin == 'http://site.a.com') {
header('Access-Control-Allow-Origin: '.$origin);
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Max-Age: 1000');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With, Cache-Control');

if (isset($_POST)) {
session_start();
$_SESSION['string'] = $_POST['string'];
echo json_encode($_SESSION['string']);
session_write_close();
}
}


Relevant code from
index.php
on domain B

<?php
$string;
session_start();
var_dump($_SESSION);
if (isset($_SESSION['string'])):
$string= $_SESSION['string'];
else:
$string= 'I like bananas';
endif;
session_write_close();
echo $string;
?>


And the script from domain A (jQuery)

$("a").click(function(e) {
e.preventDefault();
var href = $(this).attr('href');
postString($("textarea").serialize(), href);
});

function postString(myString, href) {
$.ajax({
type: 'POST',
url: 'http://domain.a.com/receive-post.php',
crossDomain: true,
data: myString,
headers: {
'cache-control':' no-cache'
}
}).done(function(data) {
console.log(data);
}).fail(function(a, b, c) {
console.log(a + b + c);
}).always(function() {
console.log("always");
var newTab = window.open(href, '_blank');
if (newTab) {
newTab.focus();
} else {
alert('Your browser blocked opening a new window.');
}
});
}


What happens



What should happen is that after clicking the link on domain A, a new tab is opened and de SESSION variable is used on there. However, this is not what happens.

The POSTing of the data works, as I can verify in console on domain B that the returned value of the SESSION variable is indeed set. The new tab is also opened. However, the SESSION variable is not used/set on that page. A
var_dump($_SESSION)
returns an empty array, meaning that there are no SESSION variables set.

Why is that? Why isn't the SESSION variable carried from page A to page B on domain B? And how do I make it usable?

Answer

You need to add withCredentials (see jQuery.ajax docs, xhrFields), otherwise cookies won’t be send/accepted for cross-domain requests.

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials:

The XMLHttpRequest.withCredentials property is a Boolean that indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates. […] In addition, this flag is also used to indicate when cookies are to be ignored in the response.


And as you said, Access-Control-Allow-Credentials: true needs to be added to the response from the remote domain, to tell that browser that it is allowed to include credentials in cross-domain requests to this URL.

Comments