How to create sessions in Node.js - node.js

In Node.js / MongoDB I want to create an easy session and give it to another page so I can know if a user is logged in or not. I want to know if he/she can access the page or not. How can I do this?
How do I set a session and how do I get the value to check if I have to redirect the user?

Use Express.js session.
It's also worth taking a look at Passport.js which makes implementing authentication in Node.js really easy.
Express.js session example:
var express = require('express');
var session = require('express-session');
var app = express();
// Make sure this is defined before any of your routes
// that make use of the session.
app.use(session({
secret: 'keyboard cat',
cookie: { maxAge: 60000 },
resave: false,
saveUninitialized: false
}));
// Access the session as req.session
app.get('/login', function(req, res) {
req.session.user = 1;
res.end('User 1 is logged in, please go to the /discussion page.');
});
app.get('/discussion', function(req, res) {
var sess = req.session;
if (typeof sess.user === 'undefined') {
res.redirect('/login');
} else {
res.setHeader('Content-Type', 'text/html');
res.write('<p>user: ' + sess.user + '</p>');
res.write('<p>expires in: ' + (sess.cookie.maxAge / 1000) + 's</p>');
res.end();
}
});

Related

Node js express Session get expired when change in code

Hi i am doing login application using node js (express framework) and mysql, for this using express-session. my session getting expires soon and also when there is change in code. I am using nodmon for automatic server response. I have attached my code here,
var session = require('express-session');
app.use(session({
secret: 'page builder',
resave: true,
saveUninitialized: false,
cookie: {secure: false, expires: new Date(Date.now() +
config.sessionTime)}
}));
setting session after user login:
app.post('/loginuser', function (req, res){
var datajsonEle = req.body;
con.query('SELECT * FROM users where userId=?', datajsonEle.userID, function (error, results, fields){
if (error){
throw error;
}else {
if(results.length > 0){
if(results[0].password === datajsonEle.userPassword){
sess = req.session;
sess.userInfo = results[0];
req.session.save();
res.end("success");
}else {
res.end("password");
}
}else {
res.end("userId");
}
// res.end(JSON.stringify(results));
}
});
});
When redirect to home.
var sess;
app.get('/', function (req, res, next){
sess = req.session;
console.log(sess);
if(sess.userInfo !== undefined){
console.log(sess.userInfo.initStage);
if(sess.userInfo.initStage === 0){
res.render('index', { title: sess.userInfo });
}else {
res.redirect('/home');
}
}else {
res.redirect('/login');
}
});
For every time when i reload after 5 min or changed my code and reload session getting empty. Please help me i am new to node js
The default store for express-session is the MemoryStore, which disappears when express restarts!
You need to use the store variable when initializing express-session to set the initialized store. The package has a list of options. Most require a persistent database somewhere (MongoDB, redis, memcache), but there is session-file-store if you're just trying things out locally.

Session variables are undefined out of the scope it is set to a value in nodejs

I am using nodejs and I am trying to access a session variable in a route which is not the same route where the session variable is defined and set. It keeps telling me that the session variable is not defined!
This is where I set the session variable:
var http = require('http');
var express = require('express');
var bodyParser = require('body-parser');
var mysql = require('mysql');
var urlencodedParser = bodyParser.urlencoded({ extended: false })
var app = express();
var dateFormat = require('dateformat');
var nodemailer = require('nodemailer');
var cookieParser = require('cookie-parser')
var session = require('express-session');
app.use(cookieParser());
app.use(session({
secret: "This_is_a_secret",
resave: false,
}));
app.post('/auth',urlencodedParser,function (req, res) {
conn.query('SELECT * FROM users WHERE user_name="'+req.body.username+'" AND user_pass="'+req.body.password+'"',function(err,res1){
if(err) {
console.log("Error!");
res.send('-2');
}
else{
if(res1.length==0) {
console.log("No matching!");
res.send('-2');
}
else if(res1.length==1){
req.session.username = req.body.username; //This is my session variable
console.log("Successful login with: " + req.session.username); //This works fine
res.send('1');
}
}
});
});
This is the second route where I am trying to access req.session.username:
app.post('/privilage',urlencodedParser,function (req, res) {
console.log("privilage: " + req.session.username); //Here is where I need to check and it says "undefined"
if(!req.session.username){
res.send('-2');
}
else res.send('1');
});
What is wrong exactly??
Thanks for all :)
You don't use store to session. It's means that sessions store in memory and reset on application restart.
app.use(session({
secret: "This_is_a_secret",
resave: false,
store: ...
}));
Be sure that you don't restart application between login and check requests.
Also I recommend to make some changes in your code
conn.query('SELECT * FROM users WHERE user_name="'+req.body.username+'" AND user_pass="'+req.body.password+'"', function(err, qres){
if(err) {
console.log("Error!", err.message);
return res.send('-2'); // Maybe best way is res.status(401).end()?
}
if (qres.length == 0) {
console.log("No matching!");
return res.send('-2');
}
if (qres.length != 1) // unbelievable case, but check it
throw new Error("Smth wrong");
req.session.username = req.body.username;
console.log("Successful login with: " + req.session.username);
res.send('1');
}

Node Express can't set session with post request

I use node express 4.0 to implement a message code verify function.
I use session to store the msg code I send.
I set up the session middleware as dos said:
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(cookieParser());
app.use(session({secret:'ssssss'}));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/uploads', express.static(path.join(__dirname, 'uploads/temp')));
but when I use post method get the msg code, I found that the session didn't set successfully.
Like this code below:
router.post('/msgCode', function(req, res) {
req.session.test = 'test';
// request send msg code api then response
}
when I repost this router I found that the req.session.test is undefined.
then I try this in another router:
router.get('/sendMsgTest', function(req, res) {
req.session.test = 'test';
res.json({
status:0
})
}
every time I request sendMsgTest, I can get req.session.test. And when I request another get method, I can get req.session.test value successfully.
So why is it my post method didn't work?
I had the same issue. I've been using fetch for requests and it does not send cookies by default, so I got different cookie ids for GET and POST requests. The solution was:
fetch(url, {
credentials: 'same-origin' // or 'include'
});
See https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials for more info.
you just try the session.save() , and in express 4 you must mention "resave" ,"saveUninitialized"
var session = require('express-session');
app.use(session({secret: 'keyboard cat', resave: false, saveUninitialized: true,cookie: { path: '/', httpOnly: true, maxAge: 30 * 30000 },rolling: true}));
router.post('/savesession', function (req, res) {
req.session.user = 'user';
req.session.save()
res.json(req.session.user);
});
router.get('/getsession', function (req, res) {
res.json(req.session.user);
});
You don't mention how you're calling the POST route. Are you sending the session cookie along with the POST request? Also, what type of response is the POST method returning?
(in app.js)
var session = require('express-session');
app.use(session({
secret: 'sooper_secret',
resave: false,
saveUninitialized: false
}));
(in routes/index.js)
router.post('/post', function (req, res) {
req.session.test = 'test';
res.json({success: true});
});
router.get('/get', function (req, res) {
const results = {
sessionData: req.session.test || 'session data not found'
};
res.json(results);
});
(command line)
% curl -X POST localhost:3000/post --cookie-jar test.cookie
% {"success":true}
% curl localhost:3000/get --cookie test.cookie
% {"sessionData":"test"}

Why can't change session's expires duration setting in connect-mongo + express.js?

app.js
app.use(express.cookieParser('your secret here'));
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/sample);
var MongoStore = require('connect-mongo')(express);
var sessionExpireTime = 10000000; // 10000 sec
var sessionStore = new MongoStore({
mongoose_connection: mongoose.connection[0],
db: config.db.name,
clear_interval: sessionExpireTime / 1000 // second
});
app.use(express.session({
secret: 'your secret here',
store: sessionStore,
cookie: {
httpOnly: false,
maxAge: new Date(Date.now() + sessionExpireTime) // millisecond
}
}));
app.get('/', function(req, res) {
if (req.session.user) {
res.render('index', {title: 'Welcome!'});
} else {
res.redirect('/login');
}
});
app.get('/login', function(req, res) {
res.render('login', {title: 'login'});
});
app.get('/auth', function(req, res) {
req.session.user = {name: 'John'};
res.redirect('/');
});
When call "/login" then redirect to "/" page.
And document created in "sessions" of the MongoDB collection.
But req.session.user is destroyed from req.session after 10 seconds.
It will return to the login screen when you reload the page.
I am aware that interval to monitor clear_interval of connect-mongo is not expired the cookie.
Will there the necessary settings of something in order to change expire duration of req.session.user?
Thank you I received your relationship to unfamiliar my English...
The maxAge property should be an absolute number of milliseconds, not a date:
cookie: {
httpOnly: false,
maxAge : sessionExpireTime
}
There are also some other issues with your code:
mongoose_connection: mongoose.connection[0]
That should be mongoose.connections[0] (or mongoose.connection, which is the same).
The clear_interval property doesn't seem to exist in (at least the current version of) connect-mongo. The way it expires sessions is using MongoDB's ttl feature (which runs once per minute).

Updating cookie session in express not registering with browser

I've set up a working login test as follows:
var express = require('express');
var fs = require('fs');
var http = require('http');
var path = require('path');
var routes = require('./routes/index.coffee');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var User = require('./userdb.coffee');
var app = express();
var RedisStore = require('connect-redis')(express);
passport.use(new LocalStrategy(function(username, password, done) {
return User.findOne({
username: username
}, function(err, user) {
if (err) {
return done(null, false, message: error);
}
if (!user) {
return done(null, false, {
message: 'Unknown user'
});
}
if (!user.validPassword(password)) {
return done(null, false, {
message: 'Invalid password'
});
} else {
return done(null, user);
}
});
}));
passport.serializeUser(function(user, done) {
return done(null, user);
});
passport.deserializeUser(function(user, done) {
return done(null, user);
});
app.configure(function() {
app.set('port', process.env.PORT || 5003);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.enable('trust proxy');
app.use(express["static"](path.join(__dirname, 'public')));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('SOMESECRET'));
app.use(express.session({
cookie: {
maxAge: 10 * 60 * 1000
},
key: 'express.sid',
secret: 'SOMESECRET',
store: new RedisStore({
port: 6379,
host: 'localhost'
})
}));
app.use(passport.initialize());
app.use(passport.session());
return app.use(app.router);
});
var check_auth = function(req, res, next) {
if (req.isAuthenticated()) {
console.log(req.session.cookie.expires);
return next();
}
return res.redirect('/login');
};
app.get('/', check_auth, routes.index);
app.get('/login', routes.login);
app.get('/logout', routes.logout);
app.post('/authenticate', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login'
}));
app.listen(app.get('port'), '0.0.0.0');
The routes and User logic is omitted, as I take it they're irrelevant to my issue, but I'll happily share them if needed (they're very small, this is just to get a small proof of concept up and running).
Login works, reading the session works, rendering templates based on session values work.
My problem is with maxAge/expires. I'm not sure where-in the problem lies, but I'll try to describe it:
When I log in, the session is saves with passport.js, stored correctly in my RedisStore, and a cookie pointing at the session is returned to the browser.
On subsequent requests the cookie is successfully found and points to the correct session from my SessionStore. req.session.cookie show an UPDATED expires and in my redis server, the TTL is reset to 10 minutes (600).
My problem is that the cookie remains at the same expirary in the browser (Chrome, windows and Mac).
So my question is: How can I debug this further?
As req.session is updated (by express, passport and connect-redis internally/automatically), I'm wondering where the problem lies, and what I should do to fix this: Cookie remains at the initial maxAges/expires.
Any tips, pointers or ideas are grately appreciated.
Express-session supports a rolling cookie expiration date. Unfortunately, it was only recently documented.
Use the "rolling" option for your session. This "forces a cookie set on every response" and "resets the expiration date." You want to set rolling to true.
Also pay attention to the "resave" option. That "forces session to be saved even when unmodified..." You'll likely want to set that option to true as well. Note that even though the default value is true for this option, you should set the value explicitly. Relying on the default for this option, rather than setting it explicitly, is now deprecated.
Try something like:
app.use( session( { secret: 'keyboard cat',
cookie: { maxAge: 60000 },
rolling: true,
resave: true,
saveUninitialized: false
}
)
);
Here's the documentation. Look under "Options" and "options.resave": https://github.com/expressjs/session .
After some digging it turns out Express does not support this sort of rolling, and is left as an exercise for the programmer to implement.
It would help if the browsers expirary was reliably readable to express, so you could bump the session only when it's close to expirary, but I use this as a workaround (inefficient) until I figure something smarter out:
check_auth = function(req, res, next) {
console.log(req.isAuthenticated());
if (req.isAuthenticated()) {
if (req.session.roll) {
req.session.roll = 0;
} else {
req.session.roll = 1;
}
return next();
}
return res.redirect('/login');
};
Where roll could be anything, the point being the session is changed (on every auth-checked request*).
*) which also means it's wildly inefficient, but it will do for now.
One alternative could be to lookup the TTL of the session id. This would have to be checked in a way like:
if ttl < 10% * maxAge (as defined by the app), as the TTL is actually correctly updated on every request, it's just that Set-Cookie isn't sent. As such, say the user stays within the 90% of maxAge, his browser-cookie will eventually expire, so even that approach is not sufficient. It could be a good middleground though.
I'll leave the question unaccepted, to encourage others to weigh in with better solutions.
just in case someone is facing this issue in Google Chrome, the solution is very easy:
app.use(cors({
allowedHeaders: ['Content-Type','Authorization'],
origin: '.dev.loc', <- your domain here, but it requires to have a dot infront
methods:['GET','POST','PUT','DELETE'],
preflightContinue: true
}));

Resources