Getting Clients Cookies in Node HTTP Server - node.js

I am trying to set/get cookies for users that browse on my web server, I found the following StackOverflow question: Get and Set a Single Cookie with Node.js HTTP Server and I was able to get the cookie set on the browser just fine. When I go to the cookie viewer I see the cookie I set just as I want it. The problem comes when I try to view the cookies, the request.headers.cookie is always undefined. How would I go about getting the cookies on a users browser, preferably without NPM modules and purely node and its own modules?
How I'm setting the cookie (this works fine, I am able to see this cookie in the browser when I go to view my cookies):
response.writeHead(statusCode, {
'Set-Cookie': cookie
})
// statusCode = 200
// cookie = 'token=SOME_TOKEN'
// In the browser I see the exact cookie I set
How I'm trying to get the cookie (not working always undefined):
let cookies = request.headers.cookie
// This returns undefined always
// even when I can view the cookie in the
// browser the request is coming from
// Also quick note: I'm currently not
// parsing the cookies out to view them as
// a JSON object because I can not get any
// of the cookies
EDIT:
It seems I have finally found the error, it sets the cookie path to be whatever path I set the cookie on, so I was setting the cookie on the "/auth" route. How can I make it so that this cookie is accessible from any route the user goes to?

Ok I finally found the solution, my error was that it was auto-setting the path of the cookie to be "/auth" so I could only access the cookie if the url requested contained "/auth", where I set the cookie I changed it to the following:
response.writeHead(statusCode, {
'Set-Cookie': cookie + '; Path=/'
})
And now I can access my cookie

Related

Express res.cookie and res.redirect not working correctly

I want to redirect with cookie to my frontend. So my code snipped like that:
const token = jwt.sign(access_info.data, config.jwtSecret);
console.log(token);
res.cookie("session_token", token, { maxAge: 900000 })
res.redirect("https://<myFrontend>.herokuapp.com/#/")
So its redirect to https:// < my Frontend > .herokuapp.com/#/ successfully.
But When I check cookie on browser, There is no cookie.
Also console.log(token); output is
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NfdG9rZW4iOiJzaHBhdF9hNzFkNDlhNjIzMTFiODY4YTVhZTQxYzI3NjZmN2U0MCIsInNjb3BlIjoid3JpdGVfcHJvZHVjdHMiLCJleHBpcmVzX2luIjo4NjM5OSwiYXNzb2NpYXRlZF91c2VyX3Njb3BlIjoid3JpdGVfcHJvZHVjdHMiLCJzZXNzaW9uIjoiMzJiYjUyMzY3MmFiYTgyMDE0MTdhMTIyNDBmODBhMTM1NTljMGQ0OWNiZmU5NmZlOTVhNDFlY2M3ZjUwYTkxMSIsImFjY291bnRfbnVtYmVyIjoxLCJhc3NvY2lhdGVkX3VzZXIiOnsiaWQiOjc2MTUxMDYyNzEwLCJmaXJzdF9uYW1lIjoiU8O8bGV5bWFuIEFsaSIsImxhc3RfbmFtZSI6IkFrcMSxbmFyIiwiZW1haWwiOiJzdWxleW1hbkBsaW5rYWRvby5tZSIsImFjY291bnRfb3duZXIiOnRydWUsImxvY2FsZSI6ImVuIiwiY29sbGFib3JhdG9yIjpmYWxzZSwiZW1haWxfdmVyaWZpZWQiOnRydWV9LCJpYXQiOjE2MzI0MzIzODB9.SeTN0KSq7MCGSyPrk8tbOPRT-EHVXPxNhDx4e9rdxbE
Why Im Getting this problem and How can I solve this? Please Help!
Unless you're checking your cookies from an area where all are listed, it's a possibility the cookie is being saved but you are in the wrong place to see it.
For example, a cookie saved on site1.com will not be shown on site2.com's storage tab in inspect element.
I've ran your code and the cookie is appearing when I check my cookies from localhost:3030 (my express API) but not on the site where it redirects :)
If you can see your cookies from, let's say, the browsers settings, then it's a problem with Express.
Also, you can shorten your code by just doing:
res.cookie("session_token", token, { maxAge: 900000 }).redirect("https://your_frontend.herokuapp.com/#/")

Not able to receive/set cookies in browser from backend in MERN app with backend hosted on heroku and frontend on netlify

I have a MERN app whose backend is hosted on Heroku and frontend on netlify. I am not able to see the cookies in the browser after deploying the app but it works fine on localhost. I think it is due to different backend and frontend ports, what am I missing, please help
You are correct. Cookies are not cross-domain compatible. If it was, it would be a serious security issue. The easiest way to fix your problem would be to send back the cookie as a res object, and then setting the cookie manually in the frontend.
Take this for example. I'll do this with JavaScript style pseudocode. Don't copy paste this as this most likely wouldn't work right away. This is what you're going to do on the back-end:
// 1. Authenticate the user.
const userData = await authenticateUser();
const userToken = await verifyUser(userData);
// 2. Return the response object.
return response.status(200).json({
status: 'success',
data: userData,
token: userToken,
});
In the front-end:
const response = await axios.post(...); // your API call, will return above object.
// set your authentication token here.
// the 'options' object will contain all possible cookie options, example would be 'secure'.
cookies.set('token', response.data.token, options);
// alternatively, set the cookie in the local storage.
localStorage.setItem('token', response.data.token);
You need to set the cookie accordingly in the front-end.
Further reading: MDN Docs
EDIT: Your question is unclear. First time you talked about cookies, but now you're talking about httpOnly cookies. Please be more specific in your questions.
It is impossible to set httpOnly cookies in React.js if it is cross-domain. React is only responsible for the 'view' of the website. httpOnly cookies are only meant to be set server-side. Client-side JavaScript cannot read or set that specific cookie, but it is able to send it. Unless you have something in your Netlify that can do server-side operations, I don't think that is possible.
Your best bet is to actually just use the same domain.

web socket is not able to read the cookie produced by http with nodejs in Safari

I have the following code that generate cookie in http and later I want the cookie is able to be read by websocket (ws)
The issue is when I open the page by localhost, the cookie is able to be produced by http nodejs controller and ws is able to access the cookie.
However, when I open the http via IP address such as 192.168.0.3, I can see the cookie is generated by http but ws is not able to read it. I have inspected the request header of ws and cookie is not included.
The above scenario works fine on Chrome browser but does not work on Safari 13.0.3
At the following is the code where I produce http cookie (I use koa2)
ctx.cookies.set('token', token, {
httpOnly: false,
expires: expiryDate,
})
At the following is how I read cookie in nodejs
let cookies = new Cookies(req, null);
console.log(JSON.stringify(req.headers)); //The header does not contain cookie in Safari 13.0.3 with IP address but in Chrome I can see the header has cookie
let token = cookies.get('token');
console.log('Cookie token is: ' + token); //token value is undefined
Please help.
OK the cause is discovered that when I call ws from html page's javascript I assigned the ws server's address as localhost and that is why when ws server receives request it cannot read the cookie set by http which is an IP address

Cookies not sent on redirect

I am building a react web application with a separate back-end express api that manages all the calls, including passporting and setting cookies. Let's call the back-end service 'api.com' and the front-end service 'react.com'. I'm using passporting with an existing provider (spotify) and after the authorization succeeds, a cookie is set on api.com. The idea is that the user interacts with react.com and requests are made to api.com via a proxy.
If I'm just testing in my browser and I make a call to api.com/resource, the cookie is automatically set. I know this because I've added a bit of logging and also because the requests that require authorization are succeeding via the cookie.
However, when I make calls to api.com from react.com via the proxy, the cookie is not set. Is this expected behavior when proxying? It seems odd that the cookie is set when I call api.com directly, but it is not set when it is redirected. Is there a way around this? My thought would be to communicate the cookie from api.com to react.com, save it there, and send it on all subsequent requests, but that seems overkill. I'm also wondering if maybe I should be setting the cookie on react.com instead of api.com.
I've tried in both Firefox and Chrome, and if it makes a difference, I'm using axios for the requests on react.com.
const request = axios({
method:'get',
url:'/api/resource'
});
This gets proxied as follows (still on react.com), using express-http-proxy:
app.use('/', proxy('api.com', {
filter: (req) => {
return (req.path.indexOf('/api') === 0);
}
}));
But once this hits api.com, any authentication fails, because the cookie is not present.
Any help is appreciated
As far as I have understood your question, I think you're not considering that cookies are set to host name.
So in the first case the hostname is same and its okay, but in the second case the browser's cookies are not set for react.com
So trying to set the cookie on react.com should work.
I would have asked for a clarification using a comment but I don't have enough reputation for that yet.

Express NodeJs cookie doesn't expire

I am using Express4 to develop a web app(a simple twitter).
I use npm package "express-session" to manage session and cookie.
But I did not set cookie.maxAge. Based on the git document we have:
By default cookie.maxAge is null, meaning no "expires" parameter is set so the cookie becomes a browser-session cookie. When the user closes the browser the cookie (and session) will be removed.
but actually, when I close my chrome and start it again, I still have the same cookie generated by server in last request.
Has anyone faced same problem? Thanks for help.
You can try:
// This user should log in again after restarting the browser
req.session.cookie.expires = false;
Each session has a unique cookie object accompany it. This allows
you to alter the session cookie per visitor. For example we can
set req.session.cookie.expires to false to enable the cookie
to remain for only the duration of the user-agent.

Resources