9

I have a PHP Script which successfully returns some simple Headers as well as a set-cookie header if called directly in the browser (or by postman). I can read the response-headers like that from chrome devTools. But as soon as I call it by Axios, the set-cookie header doesn't show up and there's no cookie saved in the browser.

I tried diffrent things like changing the response-headers server-side and using "withCredentials: true" with axios, but nothing worked. I don't even get an error or any cors-related problems.

PHP:

header("Access-Control-Allow-Origin: http://localhost:8080");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST, GET");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
header("Access-Control-Max-Age: 99999999");
setcookie("TestCookie", "Testing", time() + 3600, "/", "localhost", 0);
die();

JS:

Vue.prototype.$http = axios.create({
    baseURL: XYZ,
    withCredentials: true
})

So my first question is why does the header appear when calling the php script directly? And how can I archive to get the header through axios too?

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
  • Have you made sure it’s not simply due to browser settings that block 3rd-party cookies? https://stackoverflow.com/a/16634941/10955263 – 04FS Feb 12 '19 at 09:38
  • Well I tried to call the Script directly with the same browser and it worked. Or does axios block something with a request? Just checked regarding your link: Chrome is not blocking third-party cookies too –  Feb 12 '19 at 09:42
  • 1
    _“Well I tried to call the Script directly with the same browser and it worked”_ - if you call it directly, it isn’t 3rd-party … – 04FS Feb 12 '19 at 09:44
  • Sorry, just updated my comment. I'm not blocking third-party cookies –  Feb 12 '19 at 09:52

4 Answers4

7

probably cookie is 'httpOnly', which means client side javascript can not read it. Therefore it is not showing in chrome cookie section. test the same request in mozilla, header will show up.

Kausha Shah
  • 309
  • 3
  • 9
  • 6
    I created a standalone command line script using axios and I also don't receive the 'Set-Cookie' in the headers. The same post request using curl does show the Set-Cookie value in the headers. Postman also receives the Set-Cookie header. I tried with javascript Fetch which also does not show the header. This is driving me crazy. – A.W. Dec 27 '19 at 14:45
5

This may not apply to your situation, but I had the same problem using axios in this standalone nodejs script.

const config = {
    url: 'https://remote.url/login',
    method: 'post',        
    headers: {
        'content-type': 'application/x-www-form-urlencoded',
    },
    data: qs.stringify({
        'email': username,
        'password': pwd
    })
}

axios(config).then(res => {
    console.log(res.headers);
}).catch(err => {
    console.log(err);
})

This returned http status 200 without set-cookie in the headers. With curl the header was correctly retrieved, but the status code was 302

After adding the following config options to axios:

maxRedirects: 0,
validateStatus: function (status) {
    return status <= 302; // Reject only if the status code is greater than 302
  },

I received the set-cookie in axios in the response.header.

{
  server: 'nginx/1.16.1',
  date: 'Fri, 27 Dec 2019 16:03:16 GMT',
  'content-length': '74',
  connection: 'close',
  location: '/',
  'set-cookie': [
    'cookiename=xxxxxxxxxxxxxxxxxxxxx; path=/; expires=Sat, 26-Dec-2020 16:03:16 GMT'
  ],
  status: '302',
  'x-frame-options': 'DENY'
}

Without maxRedirects: 0 I received the html of the homepage of the remote url I used.

Without validateStatus I received the set-cookie header in the err.response.headers object.

A.W.
  • 2,858
  • 10
  • 57
  • 90
  • 1
    This worked for me as well. THANK YOU. 3 hours of my life... ``` maxRedirects: 0, validateStatus: function (status) { return status <= 302; // Reject only if the status code is greater than 302 }, ``` – Akim Khalilov Apr 20 '23 at 19:19
3

In my case, the network panel showed that the response had the 'Set-Cookie' header, but in axios the header wouldn't show up, and the cookie was being set.

For me, the resolution was setting the Access-Control-Expose-Headers header.

Explanation:

From this comment on an issue in the axios repository I was directed to this person's notes which led me to set the Access-Control-Expose-Headers header -- and now the cookie is properly setting in the client.

So, in Express.js, I had to add the exposedHeaders option to my cors middleware:

const corsOptions = {
  //To allow requests from client
  origin: [
    "http://localhost:3001",
    "http://127.0.0.1",
    "http://104.142.122.231",
  ],
  credentials: true,
  exposedHeaders: ["set-cookie"],
};

...

app.use("/", cors(corsOptions), router);

It was also important that on the axios side I use the withCredentials config in following axios requests that I wanted to include the cookies.

ex/

const { data } = await api.get("/workouts", { withCredentials: true });
jnotelddim
  • 1,806
  • 17
  • 32
  • Hello, I was wondering if you got this to work in a production environment. I have the similar set up with React + Flask and it all works locally (supposedly because cookies are shared between ports????), but once deployed in production, it doesn't work. – jeff Apr 25 '22 at 16:33
  • Hmm... it's a while back now and it was just a side-project of mine, so it's hard to remember. I think I had this stuff deployed, but not in any major way. It's possible that I never did though and it was always just local. Sorry I can't give you a more definitive answer @TheVisionary – jnotelddim Apr 27 '22 at 18:33
1

For me is working adding {withCredentials: true} like this:

axios
.post(url, {
    foo: foo,
    baz: baz,
    }, {withCredentials: true})
.then(.............
Ionut B.
  • 351
  • 3
  • 6