Reputation: 5106
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".
Any idea how to make it work?
Upvotes: 28
Views: 90450
Reputation: 53169
I had to include credentials: 'include'
in the fetch
options:
fetch('...', {
...
credentials: 'include', // Need to add this header.
});
Upvotes: 3
Reputation: 755
From Differences from jQuery section of the Fetch API on Mozilla:
Upvotes: 8
Reputation: 505
I spent a long time but nothing worked for me.
after trying several solutions online this one worked for me.
Hopefully it will work for you too.
{
method: "POST",
headers: {
"content-type": "API-Key",
},
credentials: "include",
}
Upvotes: 0
Reputation: 5106
The problem turned out to be with the fetch option credentials: same-origin/include
not being set.
As the fetch documentation mentions this option to be required for sending cookies on the request, it failed to mention this when reading a cookie.
So I just changed my code to be like this:
fetch('/login/local', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
credentials: 'same-origin',
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
}),
}).then(res => {
return res.json();
}).then(json => {
if (json.success) {
this.setState({ error: '' });
this.context.router.push(json.redirect);
}
else {
this.setState({ error: json.error });
}
});
Upvotes: 17