Node w/Express req.session undefined in controller.js - node.js

I am new to Node, so this may be obvious. In my app's main.js file, I have a route with a call back function that successfully sets the user's session info ( UserID). Basic example :
App.get("/setID", function(req,res){
req.session.UserID = ‘Fred’;
res.send(“User ID Set”);
})
This works, but I want practice organizing code with routers and controllers. When I move the code to controller.js like this:
Exports.setSessionUserID = function(req,res){
req.session.UserID = ‘Fred’;
res.send(“User ID Set”);
}
I get an error that says that req.session is undefined:
TypeError: Cannot set property 'UserID' of undefined.
If I comment out the req.session line, I do get the res.send successfully, so the router is calling this function correctly.
I belive that controller.js has all of the relevant "requires" (bodyParser, Express-sessions) that are present in main.js.
Why would calling theis function from a controller be any different (regarding sessions) than calling it from main.js?

The only problem here is that you are trying to set a property on req.session which itself is undefined, and you can't do that
// you can do
Exports.setSessionUserID = function(req,res){
req.session = { UserId: `Fred` }
res.send(“User ID Set”);
}
An Example
let req = {};
req.session = { UserId: `Fred` };
console.log(req.session.UserId);

Related

"req.session.user = user" where user is not defined

I had read almost every possible threads, post, questions, I got on setting session cookies, still didn't get the perfect solution.
I had created a web application where I want to set sessions cookies who had logged in.
Not able to figure out why the "user" is undefined. Where did I lack? I had did every trail and error to figure out the error.
App.js file
const session = require('client-sessions');
app.use(cookieParser());
app.use(session({
cookieName: 'sessioncookie',
secret: 'long_string_which_is_hard_to_crack',
duration: 30 * 60 * 1000,
activeDuration: 5 * 60 * 1000,
}));
Routes.js file
router.post('/login', (req, res) => {
const emaild = req.body.email;
const passd = req.body.pass;
db.collection('check').findOne({email: emaild}, (err, result) => {
if (err) return console.log(err);
console.log(result.passcode);
console.log('Retrived from database');
bcrypt.compare(passd, result.passcode, function(err, boolean) {
console.log(boolean);
if(boolean == true) {
req.session.user = user; //// It's Undefined
res.redirect('/dashboard');
} else {
res.send('<h1>Wrong Password</h1>');
}
});
});
});
When you query your collection with findOne method it will return you the related document ( here user which you name it result ) and you should name it with a meaningful parameter like user and then user becames available within this callback function.
Also when you get the following error on req.session.user = user;:
Cannot set property 'user' of undefined
It means that req.session is undefined. Using express, setting session on request is doing by session middlewares. here you are using client-sessions which attachs session by cookieName option value you pass it at initialization. so you should set it like the following:
req.sessioncookie.user = user;
Note that middleware ordering does matters. you should configure you application using middlewares before setting up your routes. this way every incoming request is populated with desired configuration you have been set up.

Restify: Calling a middleware within a middleware

I have a middleware for authentication which decrypts the token in the header and put the userId from the token to req.userId. Otherwise it throws an error if token doesn't exists or is invalid.
I call it like this in routes where I need authentication:
server.get('/api/somecall', authMiddleware, callService.somecall);
Now I will also have some routes which will carry a user ID in its params, like this:
server.get('/api/somecall/:userId', callService.somecall);
Here :userId can be a Mongoose Object ID or just me.
So I want to write another middleware which will be called for all routes that looks for particular params like userId and/or adminId. And if their value equals me, I want to make sure that authMiddleware automatically comes to action, PLUS replace me with the logged in user's ID so the callService.somecall handles the logic inside as it received a Mongoose Object ID.
There are two problems I'm facing:
How do I get req.params.userId in a middleware which is called before server.get(...)?
Suppose if I get req.params.userId somehow, how do I make the middleware to:
perform some condition (check if req.params.userId === 'me'),
then call authMiddleware so that I get req.userId from token, and
then perform more actions (replace req.params.userId = req.userId
then call next() to continue.
Your question is a little confusing so I don't know if this will help, but why not do something like this:
server.get('/api/somecall/:userId', otherMiddleware, callService.somecall);
function otherMiddleware(req, res, next){
if(req.params.userId === 'me'){
authMiddleware(req, res, next);
}
// Do other stuff here.
next();
}

req.session has no method 'touch'?

I'm trying to use express-session with connect-redis to store user sessions. Currently, after a user logs in, I return back req.sessionID and then whenever the user wants to make a request to a secure part of the api, he/she has to provide the session ID. The authentication middleware then goes back into redis and checks to see if the session exists and if so, replace the current session with the one stored in Redis.
function isLoggedIn(req, res, next){
var session_id = req.body.session_id;
if (!session_id){
res.send(401, {status: 0, message: "Not authorized"});
return;
}
console.log(req);
sessionStore.get(session_id, function(err, session){
if(err){
res.send(401, {status: 0, message: "Not authorized"});
return;
}
req.session = session;
req.sessionID = req.body.session_id;
return next();
});
}
But for some reason, this error shows up:
/node_modules/express-session/index.js:269
req.session.touch();
^
TypeError: Object #<Object> has no method 'touch'
I can't seem to find anyone else online that has this error because touch() is a built in functionality to express-session. Please help? My express-session version is 1.9.3.
I was having the same error. It seems that if you're coming from express cookie sessions, it was possible to set req.session = {/* some arbitrary session object */}. Obviously, req.session has some methods on the instance that express needs.
So, just make sure you're not explicitly overriding req.session anywhere in your code.
Try this:
req.session.user = { 'id': 123 };
req.session.pageviews = 1; // This too
Font: https://davidburgos.blog/expressjs-session-error-req-session-touch-not-function/

express.js not saving session data on nodeunit tests

Update at bottom!
My node.js server uses express.js to manage sessions. Upon login, I store some user information in req.session. I have a logout endpoint that simply deletes the user data from req.session before sending its response.
With every request the user makes, I use authentication middleware to make sure there is still user data in the session, so deleting user data in the session object should fail any subsequent authentication.
To test my server, I have a nodeunit test that logs in, calls a few endpoints, logs out, and then attempts to call another endpoint. I would expect the last endpoint to fail in authentication because I previously blew away user data. Instead, when I make the last call, my user data is still there. It's as if the logout call that deleted it was not written back into the session store.
Here's my app.js:
app.use(express.cookieParser('secretPassword'));
app.use(express.cookieSession({key: 'someKey'}));
...
app.get('/logout', accounts.logout);
app.get('/account', auth.authenticateSession, accounts.show);
auth.js:
exports.authenticateSession = function(req, res, next) {
if (!req.session.user) {
return res.json(401, {
error: 'Access denied. You must be logged in to make this request.'
});
}
...
}
accounts.js:logout:
exports.logout = function(req, res) {
req.session.user = null;
res.send('Logged out');
};
Unit tests:
step1_logIn : function(test) {
var postData = qs.stringify({
accountname: 'testAcct',
accountpassword: 'hello'
});
ct.postAndCall('/login', null, postData, function(resData, res) {
myCookie = res.headers['set-cookie'];
test.ok(res.statusCode === 200);
test.done();
});
},
step2_logout : function(test) {
ct.getAndCall('/logout', myCookie, function(data, res) {
test.ok(data === 'Logged out.');
test.ok(res.statusCode === 200);
test.done();
});
},
step3_ensureLoggedOut: function(test) {
ct.getAndCall('/account', myCookie, function(data, res) {
test.ok(res.statusCode === 401);
test.done();
});
}
When the tests run, execution goes through logout successfully, then into authenticateSession on the call to /account and at this point, req.session.user still exists! Why!?
Is my cookie store giving me stale data?
Is there a way to force express to save my session data manually, or do I just modify the req.session object and trust that it's going to save it?
Update:
It looks like this problem is directly related to the app middleware surrounding cookies. When I use app.use(express.session()) instead of app.use(express.cookieSession(...)), the session data is properly blown away and my tests pass.
I figured it out. Apparently express.cookieSession(...) is meant to be a set-once type of storage. Subsequent requests will have access to the session data that was initially set, but changing the req.session object won't save back new session data.
To fix the problem, I switched over to use express.session(...) which uses a server-side store for session vars.

node.js mongoose session issues. Undefined when defined?

im developing a small application with login and having an issue accessing session data.
nb: using express 3.0, coffee-script and mongoose
So in my app I have the following:
app.locals.use (req,res) ->
res.locals.session = req.session
res.locals.title = config.title
res.locals.href = config.href
In my login.coffee I do the following:
ModelUser.findOne {email: email, password: password}, (err, results) ->
if err then console.log err
if results?
req.session.user = results
req.session.authenticated = true
res.redirect '/'
else
req.session.error = 'bad login'
res.redirect '/'
If I go to output #{session.user} in Jade, I get [bject,Object], but if I enter in "name" or "email" it returns blank. If I go into console and log the session object in the app.coffee, you can see the following:
if req.session? then console.log req.session.user
returns:
{ _id: '4f9b60ba7a7ab7e7f711920e',
email: 'foobar#gmail.com',
name: 'Demo User',
password: '078d2bf82ee269cd9577588d212655c3a2162dc5b09e7c29c6a343926ee881a9' }
But if do console.log req.session.user.email it gives me a 500 error saying its not defined.. but I dont know why because you can see it is defined.
EDIT:
Solved; It was an async issue with the application continuing on before it got the user.
Had to send a callback to the find and use next()
if req.session.authenticated
require('./lib/getUser')(req.session.uid, (results) ->
res.locals.user = results
console.log res.locals
done()
)
else
done()
There is an async issue with the application flow. The server is continuing before the results are returned, thus being undefined.

Resources