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

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`);

Related

Why the my NodeJS application can't read cookies via "req.cookies"? and it shows it as a null?

My application assigns refreshToken to the reponse object as following:
newRefreshToken, { httpOnly: true, secure: true, sameSite: 'None', maxAge: 24 * 60 * 60 * 1000 });
And when I check the Postman I see the assigned JWT token there like below:
jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InFAcS5jb20iLCJpYXQiOjE2NTQ4MDMxMzIsImV4cCI6MTY2MjU3OTEzMn0.ustL6WVKWog53jAe8IFlaLw9g4BL7F1LJg5qc94F4TI; Path=/; Secure; HttpOnly; Expires=Fri, 10 Jun 2022 19:32:11 GMT;
But when I try to read the cookies using req.cookies I get this result after printing out the req object:
cookies: [Object: null prototype] {},
signedCookies: [Object: null prototype] {},
This is my server.js file content:
require('dotenv').config();
const express = require('express');
const app = express();
var passport = require('passport');
const path = require('path');
const cors = require('cors');
const corsOptions = require('./config/corsOptions');
const { logger } = require('./middleware/logEvents');
const errorHandler = require('./middleware/errorHandler');
const verifyJWT = require('./middleware/verifyJWT');
const cookieParser = require('cookie-parser');
const credentials = require('./middleware/credentials');
const mongoose = require('mongoose');
const connectDB = require('./config/dbConn');
const PORT = process.env.PORT || 3000;
// initializing passport
app.use(passport.initialize());
// Connect to MongoDB
connectDB();
// custom middleware logger
app.use(logger);
// Handle options credentials check - before CORS!
// and fetch cookies credentials requirement
app.use(credentials);
// Cross Origin Resource Sharing
app.use(cors(corsOptions));
// built-in middleware to handle urlencoded form data
app.use(express.urlencoded({ extended: false }));
// built-in middleware for json
app.use(express.json());
//middleware for cookies
app.use(cookieParser());
//serve static files
app.use('/', express.static(path.join(__dirname, '/public')));
// routes
app.use('/', require('./routes/root'));
app.use('/register', require('./routes/register'));
app.use('/auth', require('./routes/auth'));
app.use('/refresh', require('./routes/refresh'));
app.use('/logout', require('./routes/logout'));
app.use(verifyJWT);
app.use('/employees', require('./routes/api/employees'));
app.use('/users', require('./routes/api/users'));
app.all('*', (req, res) => {
res.status(404);
if (req.accepts('html')) {
res.sendFile(path.join(__dirname, 'views', '404.html'));
} else if (req.accepts('json')) {
res.json({ "error": "404 Not Found" });
} else {
res.type('txt').send("404 Not Found");
}
});
app.use(errorHandler);
mongoose.connection.once('open', () => {
console.log('Connected to MongoDB');
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
});
If you are in development i.e If you are working on localhost, try setting secure: true to secure: false when you are setting cookies in
res.cookie('jwt', newRefreshToken, {
httpOnly: true,
secure: false, //changes secure
sameSite: 'None',
maxAge: 24 * 60 * 60 * 1000
});
source problem : https://github.com/expressjs/express/issues/4924
answerer by dnrahmath

connect.sid not getting stored in cookie

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 });

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);

req.session is undefined nodeJS

im trying to set up a session in NodeJS and use it in my /auth route after that but i'm getting undefined troubles with the session.
In the app.js :
const express = require('express'),
path = require('path'),
bodyParser = require('body-parser'),
cors = require('cors'),
mongoose = require('mongoose'),
config = require('./config/DB');
const app = express();
const session = require('express-session')
const MongoStore = require('connect-mongo')(session);
mongoose.connect(config.DB, { useNewUrlParser: true }).then(
() => { console.log('Database is connected') },
err => { console.log('Can not connect to the database' + err) },
options
);
const db = mongoose.connection
const adUnitRoutes = require('./routes/adunit.route');
const userProfileRoutes = require('./routes/userprofile.route');
app.use('/adunits', adUnitRoutes);
app.use('/userprofile', userProfileRoutes);
app.use(session({
secret: 'my-secret',
resave: false,
saveUninitialized: true,
store: new MongoStore({ mongooseConnection: db })
}));
In the route :
userProfileRoutes.route('/authentification').post((req, res) => {
console.log('req session : ' + req.session.userId);
//here I got cant read property of userId because session is undefined
});
This happens because you are setting your routes before adding the middleware. Your handlers are essentially middleware so if they are added before session, your session has not been processed and added to the request yet.
Adding the routes after setting your middleware will make it work as expected.
See this minimized example:
const express = require('express');
const app = express();
const session = require('express-session');
app.get('/broken', (req, res) => {
console.log('req session : ' + req.session.userId);
res.write(String(req.session.userId));
req.session.userId = 1;
res.end();
});
app.use(
session({
secret: 'my-secret',
resave: false,
saveUninitialized: true
})
);
app.get('/ok', (req, res) => {
console.log('req session : ' + req.session.userId);
res.write(String(req.session.userId));
req.session.userId = 1;
res.end();
});
app.listen(8089);

Cannot connect redisStrore to express-session

Code:
Express.js
'use strict';
module.exports = function(app, io, server) {
var express = require('express');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
app.use(bodyParser.json({ type: 'application/vnd.api+json' }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('X-HTTP-Method-Override'));
// Redis
const redis = require('./utils/redis.js')();
app.set('redis', redis);
let isSessionCreated = false;
app.use('*', (req, res, next) => {
if(!isSessionCreated) {
isSessionCreated = true;
require('./middleware/sessionConfig.js')(app);
next();
}
});
// Passport
require('./middleware/passport.js')(app);
// Start Socket
require('./middleware/startSocket')(app, io);
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/dist'));
// Start Webpack
require('./webpack/startWebpack.js')(app);
// routes ==================================================
require('./routes/routes')(app); // configure our routes
require('../config/webpack.dev.js');
}
redis.js
'use strict';
const redis = require('redis'),
session = require('express-session'),
redisStore = require('connect-redis')(session),
redisClient = redis.createClient(),
uuid = require('uuid'),
cookieParser = require('cookie-parser');
module.exports = function() {
console.log('Redis started');
// Connects to Redis Store
const sessionStore = new redisStore({
host: '127.0.0.1',
port: 6379,
client: redisClient,
ttl : 3600000
});
redisClient.on('error', (err)=> {
console.log('could not connect ', err);
});
// Checks for Redis Connection
redisClient.on('connect', ()=> {
console.log('redis connected');
});
return {
set: function(obj) {
console.log('set called: ', obj);
redisClient.set(obj.id, obj.token);
},
sessionStore
}
}
sessionConfig.js
'use strict';
module.exports = function(app) {
const cookieParser = require('cookie-parser'),
session = require('express-session'),
uuid = require('uuid');
// Sets up Express Session
app.use(cookieParser());
console.log('session created');
let redis = app.get('redis');
app.use(session({
name: 'irelief',
secret: 'irelief',
store: redis.sessionStore,
cookie: {
cookieName: 'xyz',
httpOnly: false,
secret: 'irelief',
secure: false,
maxAge: 360000000
},
genid: function(req) {
return uuid.v4();
},
saveUninitialized: false,
resave: true,
rolling: true
}));
}
OUTPUT OF req.session on app.get('/', (req, res))
session: Session {
cookie:
{ path: '/',
_expires: 2017-07-30T22:38:34.653Z,
originalMaxAge: 360000000,
httpOnly: false,
cookieName: 'xyz',
secret: 'irelief',
secure: false } }
I have tried all that was said across any communities, nothing helps so far.
The same problem persists with passport.js
Any help will be awesome

Resources