I have a node backend, which should allow cross origin request from my frontend application that is running on localhost:3000. Therefore I've restricted the cors policy to my domain.
import csrf from 'csurf';
app.use(
cors({
origin: 'http://localhost:3000',
credentials: true
})
);
const csrfProtection = csrf({
cookie: {
maxAge: 900,
domain: 'http://localhost:3000'
}
})
router.get('/csrfToken', csrfProtection, async (req, res, next) => {
res.json({ token: req.csrfToken() });
});
When I'm making now a request to my server endpoint (which is running on localhost:5000), it returns me the following error that the cookie cannot be set.
fetch('http://localhost:5000/csrfToken', {
method: 'GET',
credentials: 'include'
})
This has nothing to do with CORS. It is just how cookies work.
The domain in the set-cookie header says http://localhost:3000 but the request is for http://localhost:5000.
That is a different origin and so is an invalid cookie.
It is impossible for a set-cookie header from one origin to set a cookie for a different origin. http://localhost:5000 can only set cookies for http://localhost:5000.
If you really want to set a cookie for :3000 then a work-around would be to provide the data through some other format than a cookie (e.g. in the request body) and then have the client-side JS on http://localhost:3000 set the cookie using the document.cookie API.
If you want to set the cookie for :5000 (which seems more likely), then get the port number right in the set-cookie header.
const csrfProtection = csrf({
cookie: {
maxAge: 900,
domain: 'http://localhost:5000'
}
})
i met this problem today too. i used chrome browser which version higher than 80.
chrome add a new attribute "samesite" to defend csrf which from v51.
chrome v80+ default limit cross-site set cookie, make cookie invalid.
console warning:
A cookie associated with a cross-site resource at http://XXX.XXX.XXX.XXXX/ was set without the SameSite attribute.
It has been blocked, as Chrome now only delivers cookies with cross-site requests if they are set with SameSite=None and Secure.
chrome://flags/ enter image description here
If anyone lands here from Laravel (sanctum), can try this for their local servers:-
//.env file. Try removing :port from SESSION_DOMAIN
SANCTUM_STATEFUL_DOMAINS="127.0.0.1:8000"
SESSION_DOMAIN="127.0.0.1"