connect.sid not getting stored in cookie - node.js

I have a node express application.
const session = require('express-session');
const config = require('config');
var MemoryStore = require('memorystore')(session);
module.exports = function (app) {
app.use(express.json());
app.use(
session({
saveUninitialized: false,
cookie: { maxAge: 86400000 },
store: new MemoryStore({
checkPeriod: 86400000
}),
resave: false,
secret: config.get('Storagehash')
})
);
app.use('/api/auth', users);
}
I have separated auth route and put it in a separate file like this. When I do console.log(req.session) I'm getting proper output.
const router = express.Router();
router.post('/', async (req, res) => {
....
req.session.isAuth = true;
console.log(req.session);
req.session.customerID = customer;
res.send(token);
}
But when I'm looking in the cookie tab, connect.sid is not getting inserted there.

Do you have a frontend application? If so, whenever you send a request to your backend you need to include withCredentials: true in your request. This will send the cookies to your backend. If you are using axios to make requests it can be done like this:
(Assuming your port is 5000)
axios.post("http://localhost:5000/api/auth/", {}, { withCredentials: true });

Related

Express session don't persist

I was making a React project, and I was using Express for backend. I set http://mini-api.moonlab.ga as a virtual host for Express server.
I sent a HTTP Request to express server with Fetch:
fetch("http://mini-api.moonlab.ga/login/", {
credentials: "include"
})
and as I expected there was a CORS error. So I installed cors package, and I set code like this in Node.js:
app.use(cors({
origin: true,
credential: true
}));
And I respond to client from server like this:
app.get("/login", (req, res) => {
const session = req.session;
if (session.miniAccount == undefined) {
session.miniAccount = Math.floor(Math.random() * 1000000);
}
res.writeHead(200, {"Access-Control-Allow-Credentials": true});
res.write(String(session.miniAccount));
res.end();
})
After I did like this, there wasn't any CORS error, but the session don't persist. When I send a request again, the session data keeps changes.
Well how to make session persist?
Server's session code:
app.use(express_session({
secret: secret.app_key,
resave: false,
saveUninitialized: true
}));
You may try setting a maxAge value inside cookie
...
const session = require("express-session");
...
app.use(
session({
secret: secret.app_key,
resave: false,
saveUninitialized: true
cookie: {
maxAge: 3600000 //session expires in 1 hr
}
})
);
I solved it myself by editing package.json.
I added "proxy": "mini-api.moonlab.ga" in package.json.
Than I edited fetch().
previous
fetch("http://mini-api.moonlab.ga/login")
new
fetch("/login")
And it worked.

Express.js - req.session variables are undefined in another controller

I know this question or similar was raised but I didn't find anything fitting to my case.
I've got login controller where I create session and its variables. Then in another controller (e.g. app.js) I want to check if user data were passed successfully. And... it's undefined. Session exists but not its variables.
Below I'm pasting some code, I hope it will clear up.
Why is this happening?
Note: cookie: { secure: false } is not working.
Edit: I've found similar question here but is it possible to resolve this without using Passport?
login.js
module.exports.login = (req, res) => {
/*some login code */
const loggedUserData = {
id: userID,
email: userEmail,
};
req.session.userData = loggedUserData;
res.json({
status: true,
userData: req.session.userData,
});
console.log(req.session.userData.id); //it's defined
};
app.js
module.exports.app = (req, res) => {
console.log(req.cookies["sid"]); //displays hash of session
console.log(req.session.id); //also it has session id, it's fine
console.log(req.session.userData); //but here is undefined
console.log(req.session.userData.id); //and here it's blowing up because `Cannot read property 'id' of undefined`
};
server.js
const express = require("express");
const session = require("express-session");
const bodyParser = require("body-parser");
const cors = require("cors");
const cookieParser = require("cookie-parser");
const loginController = require("./controllers/login");
const appController = require("./controllers/app");
const { PORT = 4001, NODE_ENV = "development", SESS_NAME = "sid", SESS_SECRET = "123", SESS_LIFETIME = null } = process.env;
const IN_PROD = NODE_ENV === "production" ? true : false;
const app = express();
app.set("query parser", "simple");
app.use(cors({ origin: true, credentials: true }));
app.use(express.static("./"));
app.use(express.json({ limit: "1mb" }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(
session({
secret: SESS_SECRET,
resave: true,
saveUninitialized: false,
name: SESS_NAME,
cookie: {
httpOnly: true,
secure: false,
sameSite: true,
secure: IN_PROD,
maxAge: SESS_LIFETIME,
},
})
);
app.get("/", appController.app);
app.post("/login", loginController.login);
app.listen(PORT, () => `Server listening on ${PORT} port`);

Express session is not keeping its data

I have a mern web app, and I'm using express session. The problem is, the cookie data is not getting saved when I try retrieving it on a different route. It gets set and outputs correctly on the same route, but when I go to another route, and try to retrieve the session data, it returns undefined.
What's weird, is that the session does get stored in mongodb, but I can't retrieve it.
What am I doing wrong and how can I fix it?
Here's the relevant code:
Session.js
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
const mongoose = require('mongoose');
module.exports = function(app) {
var sess = {
secret: 'mySecret',
cookie: { token: null },
saveUninitialized: false,
resave: true,
store: new MongoStore({ mongooseConnection: mongoose.connection })
};
if (app.get('env') === 'production') {
app.set('trust proxy', 1);
sess.cookie.secure = true;
}
app.use(session(sess));
};
Route.js
module.exports = function(app) {
app.use(cors());
app.use(helmet());
require('../middleware/session')(app);
// Other routes...
};
File1
router.post('/', async (req, res) => {
req.session.token = 'hello';
console.log(req.session.token); // Outputs 'hello'
res.send(req.session.token);
});
File2 This gets called After the page reloads
router.get('/me', async (req, res) => {
console.log(req.session.token); // Outputs undefined
console.log(req.session);
// Outputs: "Session {
// cookie: { path: '/',
// _expires:null,
// originalMaxAge: null,
// httpOnly: true }
// }
res.send(req.session.token);
});
You should add the code below in your app.js file
var cookieParser = require('cookie-parser');
var session = require('express-session');
app.use(cookieParser());
app.use(session({secret: "Funny secret"}));
That's the simple way to do it. Then you may be able to assign and access values to the req.session object.

exporting/using express-session in another file

What's the best/common way to use an express-session in other files? I have trouble integrating the session into my code. I was using auth tokens, but I would like to use sessions instead.
I defined session in my server.js:
const express = require('express');
var session = require('express-session');
var cookieParser = require('cookie-parser');
var app = express();
app.use(cookieParser('secret'));
app.use(session({
key: 'user_sid',
secret: 'secret',
resave: false,
saveUninitialized: false,
cookie: {
expires: 600000
}
}));
// stuff
module.exports = {app, session};
And it works fine! But When I try to use it in my userController.js:
var express = require('express');
var {session} = require('./../server');
module.exports.login = (req, res) => {
var body = _.pick(req.body, ['email', 'password']);
User.findByEmailAndPassword(body.email, body.password).then((user) => {
// console.log(req.session); // is undefined
res.render('dashboard.hbs');
}).catch((e) => {
res.status(400).send();
});
}
then req.session is undefined.
I know what I'm doing isn't right, obviously, but what's the right way to do it?
Thanks!
I think you don't have to export session at all, as you are telling your app to use it in server.js.
So the working fiddle should be looking like the following:
const express = require('express');
var session = require('express-session');
var cookieParser = require('cookie-parser');
var app = express();
app.use(cookieParser('secret'));
app.use(session({
key: 'user_sid',
secret: 'secret',
resave: false,
saveUninitialized: false,
cookie: {
expires: 600000
}
}));
// stuff
module.exports = app;
and your controller:
module.exports.login = (req, res) => {
var body = _.pick(req.body, ['email', 'password']);
User.findByEmailAndPassword(body.email, body.password).then((user) => {
// console.log(req.session); // is undefined
res.render('dashboard.hbs');
}).catch((e) => {
res.status(400).send();
});
}
I am considering that you are going to use this exported login function for a route, like
app.use('/login', require('yourCtrl.js').login);

Node-Client-sessions vs express-session

I have this Node API that frontends a backend OAuth server. At the end of the SAML OAuth dance, I set the Bearer Token in a browser cookie.
// need cookieParser middleware before we can do anything with cookies
app.use(express.cookieParser());
// set a cookie
app.use(function (req, res, next) {
// check if client sent cookie
var cookie = req.cookies.cookieName;
if (cookie === undefined)
{
// no: set a new cookie
var randomNumber=Math.random().toString();
randomNumber=randomNumber.substring(2,randomNumber.length);
res.cookie('cookieName',randomNumber, { maxAge: 900000, httpOnly: true });
console.log('cookie created successfully');
}
else
{
// yes, cookie was already present
console.log('cookie exists', cookie);
}
next();
});
app.use(express.static(__dirname + '/public'));
Now I was introduced to a fancy NPM which does pretty much the same thing https://github.com/mozilla/node-client-sessions
While I was almost inclined on using this NPM, I bumped into express-session. https://github.com/expressjs/session - this is for server side sessions. But this also sets a cookie
var express = require('express');
var session = require("express-session");
var app = express();
app.use(session({
resave: true,
saveUninitialized: true,
secret: 'ABC123',
cookie: {
maxAge: 60000
}
}));
app.get("/test", function(req, res) {
req.session.user_agent = req.headers['user-agent'];
res.send("session set");
});
If my need to set only a bearer token in the browser cookie for subsequent API calls, which option should be my choice?
express-session is my go to.
If you look at what it took to accomplish the same thing with the two different methods, I think the answer is clear.
If all you want to do is set a client cookie that will enable the server to correctly authenticate future requests, express-session is awesome.
Here is an example set from another question I answered that uses MongoDB as a backend to store your sessions:
'use strict';
var express = require('express'),
session = require('express-session'),
cookieParser = require('cookie-parser'),
mongoStore = require('connect-mongo')(session),
mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/someDB');
var app = express();
var secret = 'shhh';
app.use(session({
resave: true,
saveUninitialized: true,
secret: secret,
store: new mongoStore({
mongooseConnection: mongoose.connection,
collection: 'sessions' // default
})
}));
// ROUTES, ETC.
var port = 3000;
app.listen(port, function() {
console.log('listening on port ' + port + '.')
});

Resources