I can't get fetch to send a cookie. I read that for cross origin request, you must use credentials: 'include'. But this still isn't giving me cookies.
Fetch html document
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div>fetch on load</div>
<script>
fetch('http://localhost:4001/sayhi', { credentials: 'include' })
.then((res) => {
return res.text();
})
.then((text) => {
console.log('fetched: ' + text);
})
.catch(console.log);
</script>
</body>
</html>
Server file:
const express = require('express');
const mongoose = require('mongoose');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
const app = express();
const cors = require('cors');
app.use(cors());
app.use((req, res, next) => {
console.log(req.path);
// this will log a cookie when several
// requests are sent through the browser
// but 'undefined' through `fetch`
console.log('cookie in header: ', req.headers.cookie);
next();
});
app.use(
session({
secret: 'very secret 12345',
resave: true,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection }),
})
);
app.use(async (req, res, next) => {
console.log(`${req.method}: ${req.path}`);
try {
req.session.visits = req.session.visits ? req.session.visits + 1 : 1;
return next();
} catch (err) {
return next(err);
}
});
app.get('/sayhi', (req, res, next) => {
res.send('hey');
});
(async () =>
mongoose.connect('mongodb://localhost/oneSession', {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: true,
}))()
.then(() => {
console.log(`Connected to MongoDB set user test`);
app.listen(4001).on('listening', () => {
console.log('info', `HTTP server listening on port 4001`);
});
})
.catch((err) => {
console.error(err);
});
The middleware that runs console.log('cookie in header: ', req.headers.cookie); returns undefined for every fetch request.
Every fetch request is also creating a new session, I believe because the cookie isn't being set.
How can I get cookies to send with fetch?
Update: Partial answer
I think adding these helped so far:
//instead of app.use(cors());
app.use(
cors({
credentials: true,
origin: 'http://localhost:5501', // your_frontend_domain, it's an example
})
);
app.use((req, res, next) => {
`res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', 'http://127.0.0.1:5501');` // your_frontend_domain, it's an example
next()
});
But I still have a problem:
In devtools, I went to 'Network' and refreshed the html file to send the request again. There I saw the response headers. I could see that the Set-Cookie header was sent but had a yellow triangle warning.
It says to set sameSite to true.
I needed to add cookie: { sameSite: 'none' } to the session options
app.use(
session({
secret: 'very secret 12345',
resave: true,
cookie: { sameSite: 'none' },
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection }),
})
);
After I did that I got a new yellow triangle warning by the cookie that said I needed to set another option on cookie- secure: true. But this means only requests that send over HTTPS will work. But I'm in development and can't send over https.
