249
votes

I am trying out the new Fetch API but is having trouble with Cookies. Specifically, after a successful login, there is a Cookie header in future requests, but Fetch seems to ignore that headers, and all my requests made with Fetch is unauthorized.

Is it because Fetch is still not ready or Fetch does not work with Cookies?

I build my app with Webpack. I also use Fetch in React Native, which does not have the same issue.

7

7 Answers

314
votes

Fetch does not use cookie by default. To enable cookie, do this:

fetch(url, {
  credentials: "same-origin"
}).then(...).catch(...);
228
votes

In addition to @Khanetor's answer, for those who are working with cross-origin requests: credentials: 'include'

Sample JSON fetch request:

fetch(url, {
  method: 'GET',
  credentials: 'include'
})
  .then((response) => response.json())
  .then((json) => {
    console.log('Gotcha');
  }).catch((err) => {
    console.log(err);
});

https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials

62
votes

Have just solved. Just two f. days of brutforce

For me the secret was in following:

  1. I called POST /api/auth and see that cookies were successfully received.

  2. Then calling GET /api/users/ with credentials: 'include' and got 401 unauth, because of no cookies were sent with the request.

The KEY is to set credentials: 'include' for the first /api/auth call too.

26
votes

If you are reading this in 2019, credentials: "same-origin" is the default value.

fetch(url).then
4
votes

Just adding to the correct answers here for .net webapi2 users.

If you are using cors because your client site is served from a different address as your webapi then you need to also include SupportsCredentials=true on the server side configuration.

        // Access-Control-Allow-Origin
        // https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api
        var cors = new EnableCorsAttribute(Settings.CORSSites,"*", "*");
        cors.SupportsCredentials = true;
        config.EnableCors(cors);
0
votes

This works for me:

import Cookies from 'universal-cookie';
const cookies = new Cookies();

function headers(set_cookie=false) {
  let headers = {
    'Accept':       'application/json',
    'Content-Type': 'application/json',
    'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
};
if (set_cookie) {
    headers['Authorization'] = "Bearer " + cookies.get('remember_user_token');
}
return headers;
}

Then build your call:

export function fetchTests(user_id) {
  return function (dispatch) {
   let data = {
    method:      'POST',
    credentials: 'same-origin',
    mode:        'same-origin',
    body:        JSON.stringify({
                     user_id: user_id
                }),
    headers:     headers(true)
   };
   return fetch('/api/v1/tests/listing/', data)
      .then(response => response.json())
      .then(json => dispatch(receiveTests(json)));
    };
  }
0
votes

My issue was my cookie was set on a specific URL path (e.g., /auth), but I was fetching to a different path. I needed to set my cookie's path to /.