get cookies from express res.cookie() in our react app - node.js

in my express i use res.cookie to post a cookie
res.cookie("jwt", token, {
expires: new Date(Date.now() + process.env.COOKIEEX * 24 * 60 * 60 * 1000),
withCredentials: true,
httpOnly: false,
});
res.status(200).json({
status: "success",
user,
token,
});
but when i send a req to that middleware from my react app using axios i find the cookie in the network > headers> set-cookie , but its not sets in the browser:
<form
onSubmit={async (e) => {
e.preventDefault();
const res = await axios.post(
"http://127.0.0.1:3000/api/v1/users/login",
{
email: "na#test.test",
password: "password#",
},
{ credentials: true }
);
}}
>
i also tried to set samesit=None and secure, its works and i can see the cookie in the browser but after refreshing the page it disappears :
res.cookie("jwt", token, {
expires: new Date(Date.now() + process.env.COOKIEEX * 24 * 60 * 60 * 1000),
withCredentials: true,
httpOnly: false,
sameSite:"None",
secure:true
});

Browsers are less and less likely to include cookies over HTTP, instead you should try to only use HTTPS when a browser is involved.
Samesite=none;secure only works over HTTPS and will not be included in requests over HTTP. When you don't include any samesite, the default is then set to Lax (I think) and that means that it will not be included in POST requests to a different site. To do cross-site requests with cookies, you need to set samesite=none;secure and use HTTPS.

As far as I know, when you work with cookies, the backend (express in your case) handle the settings of the cookies in your browser [SESSION], in an another word, you just need to set { credentials: true } in your frontend app, the token that was saved on your browser is logically saved in your DB, so whenever a request coming, there is a check on the DB if the two tokens matches [ the one coming from the req and the one is saved on your DB ].
So mainly, or again as I know it's not gettable in other word if you just need something which is included in your token, just send it explicitly.

Related

Why am i not getting the cookies at different path

Why am i getting a authorization header when i send the requests to / from the client but when i send requests to /auth/signup on the same origin i'm not getting the authorization headers.
Here is how i'm setting my cookie in the browser so that i will send them as a header from the browser.
export const storeRefreshToken = (res: Response, token: string): void => {
// Invalidate old tokens
res.cookie(__cookieName__, token, {
httpOnly: true, // they can not be accessed using javascript
path: "/",
sameSite: "lax",
});
};
I'm using jwt authentication and graphql, I'm getting the headers when i'm at / but if i change to /auth/signin I'm not getting anything. What may be posibly the problem when setting cookies.

Not Able to Set Cookie using NodeJs in Browser Application tab even its coming in response

I am in a weird situation where cookie is not getting set in browser and in response its showing in browser
Response Screenshot from Network Tab
React Application Running on Domain - https://2367cc15b.eu.ngrok.io
Node Js Running On Domain - https://e17b14c2835b.ngrok.io
Code to set cookie
res.cookie('holofyKey', holofyKey, { httpOnly: true, domain: '.ngrok.io', expires: new Date(new Date().getTime() + (1000 * 60 * 60 * 24 * 365)) });
I am using app.use(cookieParser()); in my middleware.
Is there something i am missing ?
PS - I tried with removing httpOnly and domain name from options still no luck
After 2 days trying every possible solution this finally worked for me
This is how you need to call the api from which you want to set the cookie.
const postHelper = async (url, body) => {
return await fetch(url, {
method: "POST",
headers: {
Accept: "applicaiton/json",
"Content-Type": "application/json",
},
body: body && JSON.stringify(body),
withCredentials: true, // should be there
credentials: 'include' // should be there
});
};
After adding this you will get CORS error so please add this line of code in your server
app.use(cors({ origin: true, credentials: true }));
And finally
res.cookie('cookieKey', cookieKey, { expires: new Date(new Date().getTime() + (1000 * 60 * 60 * 24 * 365)), secure: true });
PS - This solution will work in case of Cross domain and same domain but in case of cross domain most browsers will not allow you to set cookie until user agree.

Next.js - can't access cookies from getServerSideProps [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I've been trying to fix this for a few hours but unfortunately, I can't understand what I'm doing wrong.
I have a Next.JS application with an external rest API (that I built using Express with an address different than the client). When the user logs in, I send a httpOnly cookie:
res.setHeader("Set-Cookie", cookie.serialize("token", token, {
httpOnly: true,
secure: process.env.MODE_ENV !== "development",
maxAge: 60 * 60 * 24 * 31,
sameSite: 'None',
path: '/',
}));
return res.status(200).send({
message: 'Logged in',
token,
email: result[0]['user_email']
});
The code above works - when I log in, I can see the cookie in 'Application' tab in Chrome.
Then in Next.JS I have a page component named index.js, and inside, there is this function:
export async function getServerSideProps(context) {
try {
const token = context.req.cookies?.token || null; // I can't get this, even though I have it in app tab
const settings = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify({})
};
Its main purpose is to get the cookie from the browser when I enter index.js, and then send it inside a POST request as authorization in order to get the values we want,
The thing is - I always get null from the token cookie, but I do see it in the Application Tab.
My API address is: 'api.domain.com/api'
My Client address is: 'client.domain.com'
Maybe it has something to do with the different subdomains or something because when I run both on localhost, everything works fine.
By the way, cors origin is: client.domain.com
What do I do wrong?
Thank you!
My mistake was sending the cookie from server to client when signing in without the domain attribute, and as I said my API address is different (it is a subdomain but it is still different). That means that the cookie can't be accessed by the client side. I only had to change this in server side:
res.setHeader("Set-Cookie", cookie.serialize("token", token, {
httpOnly: true,
secure: process.env.MODE_ENV !== "development",
maxAge: 60 * 60 * 24 * 31,
sameSite: 'None',
path: '/',
}));
To this:
res.setHeader("Set-Cookie", cookie.serialize("token", token, {
httpOnly: true,
secure: process.env.MODE_ENV !== "development",
maxAge: 60 * 60 * 24 * 31,
sameSite: 'None',
domain: '.domain.com', // Added this line
path: '/',
}));
Without the line above (the domain attribute), the client's browser won't be able to send the cookie to our API. It is a good thing basically because it can help us secure the system.

Cookies are not persisted even with withCredentials set to true

For the authentication my server (nestjs) sends back a cookie with the token.
This is done like this:
#SetCookies()
#Post("account/signin")
async signin(#Body() dto: LoginDto, #Req() req, ){
const token = await this._authService.signin(req.user);
const options: CookieOptions = {
expires: moment().add(10, "days").toDate(),
signed: false,
secure: false,
sameSite: false,
httpOnly: true,
};
req._cookies = [
{
name: "SESSIONID",
value: token,
options: options,
}
];
}
And it works! At least postman shows me that the cookie was successfully created and send back.
But when Angular calls the API like this:
public signin(dto: LoginDto): Observable<any>{
return this._httpClient.post("http://localhost:3000/account/signin", {
username: dto.username,
password: dto.password,
}, {
withCredentials: true,
})
}
The set-cookie is send back visible in the network tab of the devtools.
Chrome devtools response headers
But the cookie is not stored in on the disk. The user is logged in but no cookie is persisted. EditThisCookie shows nothing and after a reload no cookie is send when a request to the server is made.
In other questions the problem got resolved by setting the secure attribute of the cookie to false, which i already tried.
I have setup cors with credentials = true on the server, without any errors on both sides while signing in.

browser doesn't store HTTPOnly cookie?

I'm sending a HTTPOnly cookie with JWT from server(node/express) to client(vue), and the browser doesn't store the cookie, I have tried with three different browsers chromium Brave and Firefox (just in case lol), in Firefox with DEV Tools -> Network -> cookies tab I can see the token is sent, but the browser never stores it.
I'm in localhost...
const token = jwt.sign(
{
id: newUser._id
},
process.env.JWT_SECRET,
{
expiresIn: process.env.JWT_EXPIRES_IN
}
);
if (process.env.NODE_ENV === 'production') cookieOptions.secure =
true;
const cookieOptions = {
expires: new Date(
Date.now() + process.env.JWT_COOKIE_EXPIRES_IN * 24 * 60 * 60
* 1000
),
httpOnly: true
};
res.cookie('jwt', token, cookieOptions);
The whole point of httpOnly cookies is to not be visible to browser-based scripts. So the browser stores them, but doesn't share them with scripts it runs.

Resources