fetch: Response cookies not being set
I’m trying to implement client login using fetch on react.
I’m using passport for authentication. The reason I’m using fetch and not regular form.submit(), is because I want to be able to recieve error messages from my express server, like: "username or password is wrong".
I know that passport can send back messages using flash messages, but flash requires sessions and I would like to avoid them.
This is my code:
fetch('/login/local', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
}),
}).then(res => {
console.log(res.headers.get('set-cookie')); // undefined
console.log(document.cookie); // nope
return res.json();
}).then(json => {
if (json.success) {
this.setState({ error: '' });
this.context.router.push(json.redirect);
}
else {
this.setState({ error: json.error });
}
});
The server sends the cookies just fine, as you can see on chrome’s dev tools:

But chrome doesn’t set the cookies, in Application -> Cookies -> localhost:8080: “The site has no cookies”.
Using form.submit() while the server sets the cookies and redirects works just fine, the problem only occurs using fetch to retrieve json, so this is why I’m posting it here.
Any idea how to make it work?
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 17
Wow. I just realized I did a major mistake.
So, I have two requests; one login request and one customer request. It is the login request that gets the set-cookie header in its response, and then the user should be loggen in.
There is an option called credentials: ‘same-origin’, which I did not send with the login request (because I thought it only needed to be sent with requests after I was logged in.)
Try this:
Make sure you don’t add the credentials: ‘same-origin’ in the header object. It is not supposed to be there. I’ve seen many do that mistake.
I had to use
credentials: 'include'on the client side andCORS_ALLOW_CREDENTIALS = Truein my django app. Also setting my cookie with127.0.0.1in localhostresponse.set_cookie('my_cookie', value=token, httponly=True, domain='127.0.0.1')My two cents: If on DEV don’t use
localhostas thedomainvalue of the Cookie, use127.0.0.1instead.Resources
I was too under the impression that
credentials: same-originis used only for sending cookies, not receiving. Thank you, I’ll try this as soon as I can.If that is indeed the solution, it might be a good idea to add this to the documentation/README.
@ramprasadgs Is the signup request the one that is supposed to set the cookies in your browser or is it a request happening before/after this request that are missing the credentials option?
It’s been a while since I worked with this, and I don’t remember exactly when to use the option. It is either one of these two cases (or both):
A) Use the option when sending the request that logs a user in aka. receives the session cookie for the server.
B) Use the option when sending all requests after the login request is sent.
I think it’s best to just use the option in all requests when debugging, and when it works, see where you can remove it. The docs are still confusing, so it’s not possible to understand if the option must be used when logging in OR when sending requests as a logged in user.
Btw, are you getting a response from the sign up request? You should be able to get a response from a login-request, but if I remember correctly, the problems starts when you’re doing the next request and the cookie is not set.
EDIT: Btw, make sure the problem is not caused by CORS issues. As your backend and fronend are on different domains (the ports are not the same), you may have to use the credentials: include option. But I don’t know how this option works, so I am not sure. https://github.com/github/fetch#sending-cookies
I don’t have any samples, its my day job 😃 for basic and even some useful apps, react experience is enough. Anything really specific might need some actual android or ios knowledge.
So, I’ve verified that my issue is not caused by the server (like not setting path or somewthing).
I opened chrome://net-internals/#events and looked at the difference between a fetch call and $.ajax call (which sets the cookie correctly).
There is one thing in particular i noticed:
$.ajax:
fetch:
See the load flags? Not sure what those are, but I guess that is what causing the problem.