MERN project | Heroku doesn't set client-side cookie - node.js

My MERN project work well on my local but when I deployed it I get 401 error while fetching user. Heroku doesn't set client-side cookie. Then I have searched on google first ı change my cookie-session to express-session and some other configuration and still, it doesn't work on Heroku.
https://github.com/olcaykaplan/passport_google
cors:
app.use(
cors({
origin: "http://localhost:3000",
credentials: true,
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
allowedHeaders: ['Content-Type', 'Authorization']
})
);
express session:
app.use(
express.session({
secret: "secret",
resave: false,
saveUninitialized: true,
store: sessionStore,
proxy: true,
cookie: {
httpOnly:true,
secure: true,
maxAge: oneDay,
},
})
);

if your client side work on local,
change secure value to false, remove proxy and sameSite
The project was working fine with the following cors and session information
app.use(
cors({
origin: "netlify url",
credentials: true,
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
allowedHeaders: ['Content-Type', 'Authorization']
})
);
const oneDay = 1000 * 60 * 60 * 24; // Equals 1 day (1 day * 24 hr/1 day * 60 min/1 hr * 60 sec/1 min * 1000 ms / 1 sec)
app.use(cookieParser("secret"));
app.use(
express.session({
secret: "secret",
resave: false,
saveUninitialized: true,
store: sessionStore,
proxy: true,
cookie: {
sameSite:"none",
//path: "/",
httpOnly:true,
secure: true,
maxAge: oneDay,
},
})
);

Related

Express-session not setting cookie in production

I'm using Redis Store to store my sessions since I use a serverless backend, and I'm running into problems to set my cookie.
My frontend and backend currently run on 2 different domains, and this is how I configured my session management:
app.use(json());
app.use(
session({
store: new RedisStore({ client: redisClient }),
secret: options.sessionSecret,
resave: false,
saveUninitialized: false,
cookie: {
secure: process.env.NODE_ENV === 'PROD' ? true : 'auto',
httpOnly: true,
maxAge: 1000 * 60 * 60 * 24 * 7,
sameSite: process.env.NODE_ENV === 'PROD' ? 'none' : 'lax',
},
})
);
As said, the issue occurs when I'm in production, when I'm in development my cookie generates as expected.
Is my session configuration incorrect? Or missing something?
TIA!
As #Brijesh mentioned, we should set a property to trust the proxy:
app.set('trust proxy', 1)
app.use(json());
app.use(
session({
store: new RedisStore({ client: redisClient }),
secret: options.sessionSecret,
resave: false,
saveUninitialized: false,
cookie: {
secure: process.env.NODE_ENV === 'PROD' ? true : 'auto',
httpOnly: true,
maxAge: 1000 * 60 * 60 * 24 * 7,
sameSite: process.env.NODE_ENV === 'PROD' ? 'none' : 'lax',
},
})
);

NodeJS Session & Passport.session() Not Save A Session On Live Server

The Problem is shows up on the paid server or when I change the server default domain to my domain.
That's My Code:
app.use(helmet.contentSecurityPolicy({
useDefaults: true,
defaultSrc: ["'self'"],
directives: directives,
scriptSrc: scriptSources,
scriptSrcElem: scriptSources,
styleSrc: styleSources,
contentTypes: contentTypes,
connectSrc: connectSources,
reportUri: "/report-violation",
reportOnly: false,
safari5: false,
}));
app.use(noCache());
app.use(helmet.noSniff());
app.use(helmet.xssFilter());
app.use(helmet.referrerPolicy({ policy: 'strict-origin-when-cross-origin' }));
app.use(bodyParser.urlencoded({ extended:
true }));
app.use(express.json());
app.use(device.capture({ parseUserAgent: true
}));
app.disable('x-powered-by');
app.use(helmet.frameguard());
app.use(helmet.ieNoOpen());
app.use(helmet.hsts({
maxAge: 3600000,
includeSubDomains: true,
force: true,
}));
app.use(cookieParser());
app.use(
session({
name: uuidv4(),
secret: process.env.SERET,
resave: true,
cookie: {
sameSite: true,
secure: true,
maxAge: 3600000,
},
saveUninitialized: false,
store: MongoStore.create({
mongoUrl: process.env.dburl,
//MONGODB URL
ttl: 24 * 60 * 60,
autoRemove: 'native'
}),
})
);
app.use(compression());
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
When I Click Login It's Redirect My To Login Page But Without Any Session.
Note: It's Working So Fine On Localhost!.
Please Help.
Best Regards,
Raqeeb Al-Nakib
I solve the problem by changing the session config as follow:
app.use(session({
name: uuidv4(),
secret: process.env.SERET,
resave: false,
proxy: true, // Set This To True
cookie: {
sameSite: true,
secure:true, // Set this to True
httpOnly: true,
maxAge: 3600000,
},
saveUninitialized: false,
store: MongoStore.create({
mongoUrl: process.env.dburl, //MONGODB URL
ttl: 24 * 60 * 60,
autoRemove: 'native'
}),
})

How to send cookies to client from node/express server?

I am having the hardest time sending cookies from my nodejs server to my browser. Below is my index.js (server side) code:
app.use(express.json());
app.use(express.urlencoded({ extended: true }))
app.use(
cors({
origin: "http://localhost:3000",
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
credentials: true
})
);
let port = process.env.PORT;
if (port == null || port == "") {
port = 5000;
}
mongoose.connect(process.env.ATLAS_URI).then(console.log("MongoDB Connection Success")).catch(err => console.log("MongoDB Connection Failed" + err))
app.use(session({
secret: 'random secret',
resave: false,
saveUninitialized: false,
// store: MongoStore.create({ mongoUrl: process.env.ATLAS_URI }),
cookie: {
expires: 7 * 24 * 6 * 60 * 1000,
secure: false,
},
}));
app.use(cookieParser())
app.use(passport.initialize())
app.use(passport.session())
app.use("/auth", auth)
I know a cookie is being created when i authenticate a user because if i uncomment out the store in app.use(session({...}) i see session IDs and cookies in my mongodb. But how can I send it to the browser?
try this config for the session options.
my version of express-session is "^1.17.2"
app.use(session({
name: 'random name',
resave: false,
saveUninitialized: false,
secret: 'random secret',
store: MongoStore.create({
mongoUrl: config.DatabaseUrl,
ttl: 14 * 24 * 60 * 60 // = 14 days. Default
})
}));
if this config does not work, check your passport authenticate function that set session true like the below example :
passport.authenticate('local.register', {session: true}, (err, user): void => {
// When res has an Error
if (err) return res.redirect('/auth/register');
return res.redirect('/');
})(req, res);

session is getting expired after closing browser in express.js

I used both cookie-session and express-session, I also specified maxAge but still, it's no use.
const expressSession = require("cookie-session");
const IN_PROD = process.env.NODE_ENV === "production";
app.use(
expressSession({
name: process.env.SESSION_NAME, //setting custom name
resave: false, // do not store if it never modified
secret: process.env.SESSION_SECRETE, // secrete key which we dont't want expose to client
saveUninitialized: false, //dont save the session which is empty
cookie: {
maxAge: 30 * 24 * 60 * 60 * 1000, //Session liftime
sameSite: true,
secure: IN_PROD, //set true when application is in production mode and false when it is in development mode
},
})
);

How to access variable inside app.use method in nodejs?

Here i am trying to access maxAge and expires inside app.use() and inside app.use() method i have session() and inside session() i am assigning maxAge and expires but it's not assiging the value to cookies.
NOTE: i am accessing maxAge and expires from a property file in real application
var maxAge = 3000;
var expires = 3000;
app.use(session({
secret: 'Test API',
name: "test",
saveUninitialized: true,
resave:false,
rolling: true,
cookie: {
maxAge: maxAge, //undifined,
path: '/',
expires: expires //undifined,
overwrite: false,
activeDuration: 24 * 60 * 60 * 1000,
ephemeral: true
}
}));

Resources