I'm currently using express-session with connect-mongodb-session to store sessions and cookies.
This is my implementation:
app.js
const store = new MongoDBStore({
uri: mongoURI,
collection: 'mySessions'
});
app.use(session({
secret: 'whatever',
store: store,
resave: false,
saveUninitialized: true,
cookie: {
maxAge: 30000 // only 30 secs to to help with testing
}
}))
app.use(express.urlencoded({ extended: true }))
app.use(async (req, res, next) => {
console.log('req.session', req.session)
try {
if (req.session && req.session.userId) {
const user = await User.findById(req.session.userId)
req.user = user
req.session.auth = true
res.locals.auth = req.session.auth
} else {
res.locals.auth = null
}
next()
} catch (error) {
console.log('auth middleware error', error)
}
})
Right now I'm using 30 seconds for maxAge so I can test the behaviour of the app.
What happens is if the user closes the browser and comes back before 30 seconds, they remain logged in. Else, the cookie is no longer valid and the user has to log in again. This is ok.
However, if the user is browsing and, after 30 seconds, they make any request, the cookie is no longer active.
I'd like to make like this:
If the user is using the app, but the 30 seconds maxAge is done, the session and cookie are renewed automatically, with a renewed maxAge, so the user doesn't have to log in again while he is using the app.
But if the user closed the browser and came back after maxAge, they are required to login again (which already happens).
Thank you.
Related
I did lot of research but I am new on this, I couldn't find something concrete.
When a user is logged-in I would like to store some user info in session like Name, Profile_picture, Id, so I can use it for example in the navigation bar.
How can I achieve this?
For example in PHP is too easy just adding this line of code the information stays in what ever page you visit (before session expire)
session_start();
$_SESSION['user_id']
You have to create an express-session: https://www.npmjs.com/package/express-sessions
and then store the session like this:
let session = require("express-session");
app.use(session({
secret: "secret",
resave: false,
saveUninitialized: true,
cookie: {secure: true,
httpOnly: true,
maxAge: 1000 * 60 * 60 * 24
}
}));
This session will be stored during your visit on the webpage. If you want to set values to the cookie, simply request the cookie in a request and set somekind of value:
router.route("/login")
.post(function(req, res) {
req.session.Auth = req.body.user // => user values?
})
You can use express-session or cookie-session(https://www.npmjs.com/package/cookie-session)
If you use cookie session & you made any change session variable or in server side, then no need to restart server.
It will help you to increase your development speed, because you, no need to restart server.
app.use(cookieSession({
name: 'session',
keys: ['key1', 'key2']
}))
app.get('/', function (req, res, next) {
// Update views
req.session.views = (req.session.views || 0) + 1
// Write response
res.end(req.session.views + ' views')
})
When i close the broswer, the session gets destroyed automatically. Following is the code in my app.js file.
const session = require('express-session');
const MongoSessions = require('connect-mongo')(session);
var mongo = require('mongodb').MongoClient;
var db_url = 'mongodb://localhost:27017/test';
app.use(session({
secret: '007',
resave: false,
saveUninitialized: false,
duration: 40*60 *1000,
activeDuration: 10*60*1000,
store: new MongoSessions({
url: db_url
})
}));
When user logs in , i store the user id of user in a session. When a user again accesses the system, it will redirect him to directly to home page. To check this:
exports.indexPage = function (req, res, next) {
if (req.session.userid == null) {
res.render('login');
} else {
res.render('index');
}
};
It works fine when i keep the browser open but close all tabs and again access the application. When i close the browser and again access the application, it redirects me to login page.
I'm not sure what duration and activeDuration are meant to be, but they aren't valid options for express-session.
Since you're not setting a maxAge value for the session cookie, it automatically becomes limited to the current browser session, meaning that it will be destroyed when you close the browser (as you already noticed).
To prevent that, configure a maximum age (in milliseconds):
app.use(session({
cookie : {
maxAge : 40 * 60 * 1000
},
secret: '007',
...
}));
I've a login page (using a HTML form) that when a user enters a password (pre-determined) they can view a site. What I would like is, when the user is logged in, a cookie timer will start and last for 24 hours, when 24 hours expires, they will have to log back in when they view the site. I've done a fair bit of research into this but am struggling a small bit to understand due to my lack of experience with Node.js. I appreciate that using a pre-determined password is poor practice but for what I'm doing, it suits.
Below is the code I have in the server.js file. I had a normal login working prior to starting with cookies so it's just the cookie part I'm having trouble with. Obviously the code below is missing something like MaxAge but I dunno where to implement it.
Thanks
function checkAuth(req, res, next) {
if (!req.session.user_id) {
res.send('You are not authorized to view this page');
} else {
next();
}
}
app.get('/home', checkAuth, function (req, res) {
res.send('if you are viewing this page it means you are logged in');
});
app.post('/login', function (req, res) {
var post = req.body;
if (req.body.name == "login"){
req.session.user_id = "login";
res.redirect('/home');
} else {
res.send('Bad user/pass');
}
});
When you initialise your session, add the maxAge to the cookie.
app.use(session({
secret: 'your secret key',
resave: true,
saveUninitialized: false,
cookie: {
secure: false,
maxAge: 1440000
}
}));
This sets the maxAge of all the cookie. Post which you can check if the request is authenticated.
I have this issue where a session is created regardless if the user is logged in or not.
I would like it if a session is created only if the user logs in successfully. Otherwise, if a selenium bot hits...for example, the route route('/users/:username') my session collection would fill up with sessions that are not from real users. I am having my users stay logged in forever, so the session cookie is set to a year...which is even worse if the session does not belong to real user.
How can I have a session returned to the client only if the authenticate successfully? I tried different order of the routes and middle ware, but this is the only order that works correctly.
app.use(session({
secret: 'bob',
saveUninitialized: true,
resave: true,
name: 'curves',
cookie: { secure: false, httpOnly: false,
maxAge: 365 * 24 * 60 * 60 * 1000 },
store: new MongoStore(storeOptions)
}));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', auth);
app.use('/api/v1', router);
// isLoggedIn WOULD NOT WORK IF I PLACED THIS BEFORE PASSPORT/SESSION MIDDLEWARE
router.route('/users/:username')
.get(isLoggedIn, api.getUsername);
auth.route('/auth/facebook')
.get(passport.authenticate('facebook', { scope : 'email' }));
auth.route('/auth/facebook/callback')
.get(function(req, res, next) {
passport.authenticate('facebook', function(err, userDoc, info) {
if (err) { return next(err); }
// I don't think !userDoc will ever happen because of mongo upsert
if (!userDoc) { return res.redirect('/login'); }
req.logIn(userDoc, function(err) {
if (err) { return next(err); }
return res.redirect('http://localhost:9000/users');
});
})(req, res, next);
});
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) { return next(); }
res.status(404).json({ error: "not logged in" });
}
Figured it out...I just needed to set saveUninitialized: false.
saveUninitialized
Forces a session that is "uninitialized" to be saved to the store. A session is uninitialized when it is new but not modified. Choosing false is useful for implementing login sessions, reducing server storage usage, or complying with laws that require permission before setting a cookie. Choosing false will also help with race conditions where a client makes multiple parallel requests without a session.
The default value is true, but using the default has been deprecated, as the default will change in the future. Please research into this setting and choose what is appropriate to your use-case.
Note if you are using Session in conjunction with PassportJS, Passport will add an empty Passport object to the session for use after a user is authenticated, which will be treated as a modification to the session, causing it to be saved.
I am trying to use connect/express cookieSession() in order to store my node.js sessions in cookies (and thus, avoiding a server-side session store). This would help me to 'remember' the user when they log in and keep sessions alive even after server restarts.
I would like to do this with cookieSession():
app.use( express.cookieSession( { secret: 'secret_key' } ) );
app.use( function (req, res, next) {
if ( req.method == 'POST' && req.url == '/login' ) {
if ( req.body.remember ) {
req.session.cookie.maxAge = 30*24*60*60*1000; // Rememeber 'me' for 30 days
} else {
req.session.cookie.expires = false;
}
}
next();
});
However, this does not work, because req.session.cookie is undefined. I also tried the following, but it didn't seem to work:
app.use( express.session( { secret: 'secret_key' } ) );
app.use( function (req, res, next) {
if ( req.method == 'POST' && req.url == '/login' ) {
if ( req.body.remember ) {
req.cookies['connect.sess'].maxAge = 30*24*60*60*1000; // Rememeber 'me' for 30 days
} else {
rreq.cookies['connect.sess'].expires = false;
}
}
next();
});
Starting out with
app.use(express.cookieSession({ secret: config.server.cookieSecret }));
And changing it to
app.use(function(req, res, next) {
express.cookieSession({
secret: config.server.cookieSecret,
cookie: {
maxAge: req.param('remember') ? 20000 : 3000
},
})(req, res, next);
})
So, we create our own middleware, wrapped around the cookieSession middleware, changing the maxAge based on a param.
So, whenever you change the session you'll need to pass a remember in the body, query, or params( that's where req.param() looks ). In most cases, you only set a user_id to the session once, at login.
It's 3 seconds or 20 seconds to test and ensure it works.
And again, it might be not very helpful if you're setting stuff to your session a lot, but if you just set a user_id to session at login, this is all you need.
If you are setting lots of stuff to your session, you should know that data get passed around at every request, and you should save only the minimum to the session, like user_id, then look up the data you need for each request, to keep the overhead down on the user.
I think this does what you want:
// Using express.session instead of express.cookieSession
app.use(express.session({ secret : 'secret_key' }));
app.use( function (req, res, next) {
if ( req.method === 'POST' && req.url === '/login' ) {
if ( req.body.remember )
{
req.session.cookie.maxAge = 30*24*60*60*1000;
// needed to make the session `dirty` so the session middleware re-sets the cookie
req.session.random = Math.random();
}
else
{
req.session.cookie.expires = false;
}
}
next();
});
cookieSession does some funky stuff, like del req.session.cookie (not sure why).
You have to first set req.session.cookie so that you can set maxAge. Trying to use it before you set it gives req.session.cookie is undefined
express.cookieSession has default values which it accepts, see here. You should mention all the parameters you are going to use. You can set cookie via the following :
app.use(express.cookieSession({ secret: 'secret_key', cookie :{ path: '/', httpOnly: true, maxAge: 30*24*60*60*1000} });
A little late to the table but I thought this answer may help people going forward...
I was using cookie-session which doesn't create a cookie object on request.session. To properly implement rememberMe functionality using request.session.cookie I switched cookie-session to express-session and that solved everything. So now there is a cookie object on session and doing this inside of a request is possible...
npm install express-session
app.post('/login', function(request, response, next) {
passport.authenticate('local', function(err, user, info) {
if(err) return next(err);
if(!user) {
request.flash('loginMessage', info.message);
return response.redirect('/account/login');
}
request.login(user, function(err) {
if(err) return next(err);
if(request.body.rememberMe)
request.session.cookie.maxAge = 2592000000;
else
request.session.cookie.expires = false;
return response.redirect(options.redirect);
});
})(request, response, next);
});
This is also pretty late but it might help other people.
It seems like to me the best way to persist your session data is to store it in something like redis. The question asked for a way that didn't use server storage, but I think he was referring more to MemoryStore. Maybe not but either way this is what I did.
I used express-session and connect-redis
npm install -g connect-redis
npm install -g express-session
Then you configure stuff.
// session modules
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session')
var redisStore = require('connect-redis')(session); // this sets up Redis to work with your session cookies
var app = express();
Then you just initiate your session with the store option set to your redisStore.
The maxAge part sets the lifetime of each session to an hour, the session middleware resets it when it's accessed.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
store: new RedisStore({
host:'127.0.0.1',
port:6380,
prefix:'sess'
}),
cookie: {maxAge: 3600000 },
secret: 'session_secret'
}));
Now when a client connects, express should store the session data automatically in a Redis data structure. Since it's not just cached in memory, your server can crash and still have all the relevant session data still available at the IP address and and port specified.
Yummy seems to allow modifying cookies expiry after creation.