Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fetch Not Sending Cookies

I am having issues in fetch sending cookies when I use the following js snippet in the console (in developer tools) of my browser (tried chrome, firefox and edge):

fetch('http://127.0.0.1:3010/check', {
  credentials: 'include'
  method: 'GET'
})
  .then(res=>res.json())
  .then(jsonobj=>{console.log(jsonbj)});

And here is my express code handling the api request:

var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var cors = require('cors');

var app = express();
app.use(cors({
    credentials: true,
    origin: 'https://www.youtube.com'
));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

app.get('/check', (req, res)=>{
  console.log(JSON.stringify(req.cookies));
  res.json({
    message: "COOL"
  });
});

The fetch call is successful with the message COOL getting logged to the browser console. However, the NodeJS console prints empty objects {} or empty cookies.

For example, when I run the fetch request in the console of http://youtube.com/, I would like the browser to send cookies on my localhost to my express server (I did this to simulate cookie sending in cross-site request).

EDIT 1: Also some of the cookies on my localhost have SameSite unset and the mdn docs says that those cookies can be sent to server in cross site requests too:

The default behavior if the flag is not set, or not supported by the browser, is to include the cookies in any request, including cross-origin requests.

Either the snippet from mdn docs is wrong or the implementations of SameSite by browsers is inconsistent. I am confused.

EDIT 2: Also this page https://textslashplain.com/2019/09/30/same-site-cookies-by-default/ says

In Chrome 80 and later, cookies will default to SameSite=Lax. This means that cookies will automatically be sent only in a first party context unless they opt-out by explicitly setting a directive of None:

Are the mdn docs really incorrect then about the default value of SameSite?

EDIT 3: I have proposed an edit to the mdn docs and it has been accepted.

like image 439
Bhushan Avatar asked Nov 18 '19 15:11

Bhushan


People also ask

Are cookies sent with Fetch?

If you set credentials to same-origin : Fetch will send 1st party cookies to its own server. It will not send cookies to other domains or subdomains. If you set credentials to include : Fetch will continue to send 1st party cookies to its own server.

Why are cookies not being sent?

If the server doesn't allow credentials being sent along, the browser will just not attach cookies and authorization headers. So this could be another reason why the cookies are missing in the POST cross-site request.

How do I send cookies to my server?

To send cookies to the server, you need to add the "Cookie: name=value" header to your request. To send multiple Cookies in one cookie header, you can separate them with semicolons. In this Send Cookies example, we are sending HTTP cookies to the ReqBin echo URL.

Does fetch send a GET request?

The fetch() method: Fetch API comes with a fetch () method that allows you to fetch data from all sorts of different places and work with the data fetched. It allows you to make an HTTP request, i.e., either a GET request (for getting data) or POST request (for posting data).


1 Answers

Please see the edits on the question before moving with this answer. Now we can no-longer send cookies with cross-site requests if the cookies have the SameSite attribute unset, since the browsers have changed the default value of SameSite to lax. The following is a snapshot from the chrome patch notes (for the stable version 80, though the beta testing will be available for version 79 beta because google believes this change will be disruptive and may cause some web apps to behave incorrectly and hence shows the warning too) at https://support.google.com/chrome/a/answer/7679408#76:

Cookies with SameSite by default, and Secure SameSite=None cookies in Chrome 80 Starting in Chrome 80, cookies that do not specify a SameSite attribute will be treated as if they were SameSite=Lax. Cookies that still need to be delivered in a cross-site context can explicitly request SameSite=None. They must also be marked Secure and delivered over HTTPS. Policies will be made available for enterprises that need to configure Chrome to temporarily revert to legacy SameSite behavior.

Also similar behavior is displayed by Firefox and Edge currently. To send the cookies in cross origin requests, we have to explicitly set the SameSite attribute to None as:

Set-Cookie: key=value; SameSite=None; Secure

Also, note Secure is mandatory, else it will be treated as a Lax cookie. Use the None option only if you are really sure about what you are doing and handling cross-site request forgery accurately!!

I had proposed changes to the mdn docs of Http Cookie (https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) and the changes have been published. Now the mdn docs say:

Previously, the default behavior if the SameSite attribute is not set, or not supported by the browser, was to include the cookies in any request — including cross-origin requests.

However, new versions of browsers default to SameSite=Lax. In other words, cookies with no SameSite attribute set are now handled as if the value of the SameSite attribute is set to Lax — which means that cookies will automatically be sent only in a first party context. To specify that cookies are to be sent in both same-site and cross-origin requests, the value must be explicitly set to None.

like image 181
Bhushan Avatar answered Oct 20 '22 01:10

Bhushan