res.cookie is undefined when server uses HTTPS - node.js

I'm using a user login logic that saves JWT in cookies.
const token = jwt.sign({
username: login,
},
process.env.JWT_SECRET);
res.cookie("jwt", token, {
secure: false,
httpOnly: true,
});
console.log(res)
return res.status(200).json({
success: true,
username: login });
The frontend making requests runs oh HTTP. When the server runs also on HTTP, everything works fine, but when I go for HTTPS, the cookie is not saved at all. Setting 'secure' to true does not help. What can be the possible reason?

use secure: true,
in your response for cookie

I have same problem lately and here is my solution for this problem.
I change my res.cookie to this
res.cookie("jwt", token, {
secure: true,
httpOnly: true,
sameSite: "None", // I add this line
});

Related

Can't not set cookie in express-session using node.js

I tried to see if my cookies is working ,so here's my code
const RedisStore = connectRedis(session)
const redisClient = redis.createClient()
app.use(
session({
//name: 'qid',
store: new RedisStore({ //ttl: how long it should last
client: redisClient,
//disableTTL :true, //make sure session last forever
//disableTouch: true, // make sure it does'nt have to update the last time it's ttl
}),
cookie:{
maxAge: 1000*60*60*24*365*10, //10 years
path: "/"
//httpOnly:true, //javascript front end can't access
//sameSite:'none', // csrf
//secure:false
//secure: __prod__ //cookie only works in https
},
saveUninitialized:true, //automatically create a empty session on default
secret: 'some secret', //env
resave: false,
})
)
app.listen(4000,()=>{
console.log('server stared on localhost:4000')
})
app.get('/products', (req,res,next) => {
console.log(req.session);
if(!req.session.userId){
req.session.userId = 1
}else{
req.session.userId = req.session.userId +1
}
console.log(req.session.userId) //test if work
res.send("hello")
})
So here's the thing, when I connect to localhost:4000/products, In the cookie session, I can only see these
But when I print out the results on vscode console, I can see the number is growing like below , so I do have a session, it's just not showing on the browser , can anyone tell me why is that?
server stared on localhost:4000
Session {
cookie: {
path: '/',
_expires: 2031-08-18T12:59:30.827Z,
originalMaxAge: 315360000000,
httpOnly: true
},
userId: 10
}
11
Session {
cookie: {
path: '/',
_expires: 2031-08-18T13:00:37.257Z,
originalMaxAge: 315360000000,
httpOnly: true
},
userId: 11
}
12
So I got a solution after a lot of tests, So if you only set your cookie to same-site:"none" without secure options ,it would be like my situation,but if you want to turn on secure option your endpoint have to be https, so I don't think this was the answer, and you can change to lax or other options it would act normal in your localhost,
Work in local host
lax
(don't set same site)
But due to secure policy https://www.chromium.org/updates/same-site you can't not pass cookie to some certain website (in my case I want to test cookies in my graphql apollo studio) without setting same-site:"none" secure, so I use mkcert to use https in my localhost
https://web.dev/how-to-use-local-https/ , and everything works,
Work
samesite : none
secure : true
https:yourendpoint

How come browser can't store cookies?

Currently, I am on a solo project, but I've got an issue that is the same as the title.
Client-side is on React with HTTPS.
Server-side is on Express with HTTPS. and they are cross-domain.
when the submit button is clicked, the code below is running.
//client side
axios
.post('https://ohmycounty.me/user/signin', {email : "byron#google.com", password: "example", {
withCredentials: true,
})
//server side
app.use(session({
secret: 'example',
resave: false,
saveUninitialized: true,
cookie: {
sameSite: 'none',
secure: true
}
}));
app.use(cors({
origin: ['https://ohmycounty.xyz'], // client app's url
credentials: true
}));
const { users } = require('../../models');
module.exports = {
post: (req, res) => {
console.log(req.session.userid)
const {
email,
password
} = req.body;
let session = req.session;
users.findOne({
where: {
email: email,
password: password
}
}).then(result => {
if (!result) res.status(401).send(JSON.stringify({
status: false
}))
else {
session.userid = result.id;
res.status(201).json({
id: result.id
})
}
})
}
}
I can't find any connect.sid on chrome developer tool applications.
Chrome Applications
Chrome Network CookieHeaders
Waiting for advice from experienced developers.
Any opinion is fine.
Please help me.
The secure attribute should be set if and only if the connection is made over HTTPs. So if you changed it to false, it should work in the dev environment.
cookie: {
secure: false
}
From the express-session doc:
cookie.secure
Specifies the boolean value for the Secure Set-Cookie attribute. When truthy, the Secure attribute is set, otherwise, it is not. By default, the Secure attribute is not set.
Note be careful when setting this to true, as compliant clients will not send the cookie back to the server in the future if the browser does not have an HTTPS connection.
Link to the doc: https://www.npmjs.com/package/express-session

Lusca csrf not working as expected - http request using old token

I was trying to set up CSRF protection with lusca on my Express.js application. Not it looks like this:
this.app.use(lusca({
csrf: {
cookie: {name: '_csrf'}
},
hsts: { maxAge: 31536000, includeSubDomains: true, preload: true },
nosniff: true,
referrerPolicy: "same-origin",
xframe: "SAMEORIGIN",
xssProtection: true,
}));
And on client side as follow:
const res = await axios.post(`${Constants.apiUrl()}/${Constants.paths.login}`,
credentials, {
withCredentials: true,
xsrfCookieName: '_csrf'
});
On the server-side, I also set some headers to be able to send cookies with request - res.header('Access-Control-Allow-Credentials', 'true').
Probably I'm missing some important part of how CSRF protection works. Now each time with the response, I'm getting new csrf token but this means that my new HTTP POST request sending the previous token that already outdated.
What I'm missing?
Finally, I found the problem after testing for 3 hours. You need to add the secret of the csrf. Also, if you are using Angular, you need to add angular: true into the csrf.
this.app.use(lusca({
csrf: {
cookie: {name: '_csrf'},
secret: 'qwerty'
},
hsts: { maxAge: 31536000, includeSubDomains: true, preload: true },
nosniff: true,
referrerPolicy: "same-origin",
xframe: "SAMEORIGIN",
xssProtection: true,
}));

Express sessions cookies are not being set for client

When I use postman with my API I can see the cookies being set on the Postman app, so when I need to do any subsquent request, the cookie can be checked to see who the user is, when I try to implement this on the client it does not set cookies.
I see the same response in the server for both cases
Session {
cookie:
{ path: '/',
_expires: 2019-12-31T19:12:25.238Z,
originalMaxAge: 720000,
httpOnly: true,
secure: false,
sameSite: true } }
when I check the frontend for cookies
and same server response...
Session {
cookie:
{ path: '/',
_expires: 2019-12-31T19:14:11.811Z,
originalMaxAge: 720000,
httpOnly: true,
secure: false,
sameSite: true } }
I have setup CORS and just not sure what is the issue, I need to know if the user is logged in , so I can setup navigation and also so I can have a user dashboard .. I need to know who the logged in user is! Please take a look at my github repo , thanks for your time.
github repo to recreate issue: https://github.com/fullstackaccount/express_connection
- mongodb local DB runs for server side.

session not persisting when using secure cookie in NodeJS with express-session

I'm using NodeJS + express + express-session to persist a userID from anywhere in the application.
On the first route, my session is defined
userProfileRoutes.route('/authentication').post((req, res) => {
req.session.userID = 10; //example
console.log(req.session)
}
The result of the console.log is:
Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: true },
userID: 10 } // this is the right value
But then, from a different route, I can't see the value:
userProfileRoutes.route('/edit').get(function (req, res) {
console.log('After the nav edit route');
console.log(req.session);
}
And this prints
Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: true }
} // ID VARIABLE DISAPEARS HERE
I am configuring express-session using these parameters:
app.use(session({
secret: 'secret',
proxy: true,
resave: false,
saveUninitialized: true,
withCredentials: true,
cookie: { secure: true },
store: new MongoStore({ mongooseConnection: db })
}));
Why is my userID not persisted between requests and on all routes?
You are setting cookie: {secure: true} but trying to access your server using HTTP.
From the express-session documentation:
cookie.secure
Note be careful when setting this to true, as compliant clients will not send the cookie back to the server in the future if the browser does not have an HTTPS connection.
Please note that secure: true is a recommended option. However, it requires an https-enabled website, i.e., HTTPS is necessary for secure cookies. If secure is set, and you access your site over HTTP, the cookie will not be set.
Make sure you are either using HTTPS (always in production!) or you set cookie.secure to false (maybe, and for development only!)
The secure flag in cookies
The secure flag is an option that can be set by the application server when sending a new cookie to the user within an HTTP Response. The purpose of the secure flag is to prevent cookies from being observed by unauthorized parties due to the transmission of a the cookie in clear text.
To accomplish this goal, browsers which support the secure flag will only send cookies with the secure flag when the request is going to a HTTPS page. Said in another way, the browser will not send a cookie with the secure flag set over an unencrypted HTTP request.
By setting the secure flag, the browser will prevent the transmission of a cookie over an unencrypted channel.
from https://www.owasp.org/index.php/SecureFlag
Cookies in express-session
Following common practice, express-session uses cookies to store a session ID and server side storage (mongoDB in your case) to store session data. If the browser does not send your session ID because it can't find a valid cookie, your server will assume there is no session, and save the user id on a new session on every request.
When you got to /authentication it will save the ID on a new session. When you try to read in in a different request, the session ID has changed and you have no value in userID.

Resources