Issue
As a start I want to say that I already read almost everything regarding this issue and so far there is no resolution.
In short I have a Node.js API server running on localhost:3000. I also have an Angular 10 app running on localhost:4200. The problem is simple – I make a request to localhost:3000/api/users/login and receive the following:
server-response
However there is no cookie saved as you can see here: empty-cookies
As a result every subsequent request be it POST or GET is without headers and the server cannot recognize the user.
So far I tried:
- including the { withCredentials: true } to the http requests from angular
- changing the cookie to http: false
- setting the domain in the cookies to various stuff like ‘.app.localhost’
- adding sameSite: ‘none’ to the cookie
- searching for the cookie on localhost:3000 where the API is running
- changing the origin in cors to ‘*’ or removing it entirely
- tried all these things in Edge as well(otherwise I use Chrome)
Unfortunately none of these things worked for me. Otherwise the login and registration are done succesfully and I can see the data in mongo.
Here I will add the snippets of the code I use:
const app = express();
app.use(express.json());
app.use(cookieParser(config.cookieSecret));
app.use(express.static(path.resolve(__basedir, 'static')));
app.use(cors({
origin: config.origin,
credentials: true
}));
app.use('/api', apiRouter);
app.use(errorHandler);
This is the login handler in which I set the cookie:
async function login(req, res, next) {
const { email, password } = req.body;
try {
let user = await User.findOne({ email });
const match = await user.matchPassword(password);
if (!match) {
res.status(401)
.send({ message: 'Wrong username or password' });
return
}
user = bsonToJson(user);
const token = utils.jwt.createToken({ id: user._id });
if (process.env.NODE_ENV === 'production') {
res.cookie(authCookieName, token, { httpOnly: true, sameSite: 'none', secure: true })
} else {
res.cookie(authCookieName, token, { httpOnly: true })
}
res.status(200).send(user);
} catch (err) {
next(err);
}
}
And here is the Angular part:
loginMet(data) {
return this.http.post('http://localhost:3000/api/users/login', data, {withCredentials: true});
}
Solution
Update
After testing it out it appears that chrome (86.0.4240.198) still allows cross site cookies on localhost
which means that your problem is not caused by the new restrictions and using { useCredentials: true }
should work fine.
Initial
For two locations to be considered to have the same origin, the protocol, domain and the port have to be the same. In your case you have (localhost:3000 and localhost:4200) and cookies cannot be shared across different origins in Safari, Firefox and from 2020 in Chrome as well.
You can read more on the topic here.
Locally you can try to solve this issue by creating proxy.config.json in order for the webpack dev server to act as a proxy to your backend. So all requests to localhost:3000 will be instead sent to localhost:4200. You can read more about it here.
Another solution that will work locally and on production (in the case that you won’t be serving the angular app from the same server as the one for the API) is to have one domain and two subdomains for the individual apps. Locally you can do this by updating the hosts file and on production of course this will be done by the DNS server.
Answered By – user1
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0