var session = require("express-session");
var Redis = require("redis");
var $redis = Redis.createClient($config.redis.port, $config.redis.host, {password: $config.redis.pass});
var RedisStore = require("connect-redis")(session);
app.use(session({
name: "secret",
secret: $config.token,
store: new RedisStore({client: $redis}),
saveUninitialized: true,
resave: true,
rolling: true,
cookie: {
httpOnly: true,
secure: false,
domain: "localhost",
expires: new Date(Date.now() + (3600 * 60))
}
}));
route:
router.get("/login", function(req, res)
{
if(req.isAuthenticated())
{
res.redirect("/");
return;
}
res.render("login");
});
Error:
express:router dispatching GET /login +55s
express:router query : /login +1ms
express:router expressInit : /login +1ms
express:router serveStatic : /login +0ms
express:router logger : /login +2ms
express:router <anonymous> : /login +0ms
express:router cookieParser : /login +1ms
express:router jsonParser : /login +1ms
express:router <anonymous> : /login +0ms
express:router csrf : /login +1ms
express:router router : /login +1ms
express:router dispatching GET /login +0ms
express:router session : /login +4ms
express:router initialize : /login +1ms
express:router authenticate : /login +0ms
express:router haltOnTimedout : /login +1ms
express:router <anonymous> : /login +0ms
express:router router : /login +1ms
express:router dispatching GET /login +1ms
express:view render "C:\app\app\views\login.ejs" +0ms
express:router dispatching GET /assets/css/main.css?v=a +16ms
express:router query : /assets/css/main.css?v=a +0ms
express:router expressInit : /assets/css/main.css?v=a +2ms
express:router serveStatic : /assets/css/main.css?v=a +1ms
express:router dispatching GET /assets/css/common.css?v=a +2ms
express:router query : /assets/css/common.css?v=a +1ms
express:router expressInit : /assets/css/common.css?v=a +0ms
express:router serveStatic : /assets/css/common.css?v=a +1ms
express:router dispatching GET /assets/css/login.css?v=a +1ms
express:router query : /assets/css/login.css?v=a +0ms
express:router expressInit : /assets/css/login.css?v=a +3ms
express:router serveStatic : /assets/css/login.css?v=a +0ms
express:router dispatching GET /assets/js/login.js?v=a +1ms
express:router query : /assets/js/login.js?v=a +1ms
express:router expressInit : /assets/js/login.js?v=a +0ms
express:router serveStatic : /assets/js/login.js?v=a +1ms
GET /login 200 13.572 ms - 1972
ReplyError: ERR invalid expire time in set
at new Command (C:\app\node_modules\redis\lib\command.js:12:22)
at RedisClient.set (C:\app\node_modules\redis\lib\commands.js:62:47)
at RedisStore.set (C:\app\node_modules\connect-redis\lib\connect-redis.js:195:18)
at Session.save (C:\app\node_modules\express-session\session\session.js:72:25)
at Session.save (C:\app\node_modules\express-session\index.js:381:15)
at ServerResponse.end (C:\app\node_modules\express-session\index.js:330:21)
at ServerResponse.send (C:\app\node_modules\express\lib\response.js:211:10)
at done (C:\app\node_modules\express\lib\response.js:962:10)
at tryHandleCache (C:\app\node_modules\ejs\lib\ejs.js:208:10)
at View.exports.renderFile [as engine] (C:\app\node_modules\ejs\lib\ejs.js:412:10)
at View.render (C:\app\node_modules\express\lib\view.js:128:8)
at tryRender (C:\app\node_modules\express\lib\application.js:640:10)
at EventEmitter.render (C:\app\node_modules\express\lib\application.js:592:3)
at ServerResponse.render (C:\app\node_modules\express\lib\response.js:966:7)
at C:\app\routes\static.js:29:7
at Layer.handle [as handle_request] (C:\app\node_modules\express\lib\router\layer.js:95:5)
However, this error maybe related to connect-redis module but wanted to post it here as it is a dependancy.
at RedisStore.set (C:\app\node_modules\connect-redis\lib\connect-redis.js:195:18)
store.client.set(args, function (er) {
RedisStore.prototype.set = function (sid, sess, fn) {
var store = this;
var args = [store.prefix + sid];
if (!fn) fn = noop;
try {
var jsess = store.serializer.stringify(sess);
}
catch (er) {
return fn(er);
}
args.push(jsess);
if (!store.disableTTL) {
var ttl = getTTL(store, sess);
args.push('EX', ttl);
debug('SET "%s" %s ttl:%s', sid, jsess, ttl);
} else {
debug('SET "%s" %s', sid, jsess);
}
store.client.set(args, function (er) {
if (er) return fn(er);
debug('SET complete');
fn.apply(null, arguments);
});
};
npm list http://pastebin.com/bQFjYeT7
[email protected]
[email protected]
[email protected]
node -v
v6.10.0
npm -v
3.10.10
redis info:
redis_version 3.0.3
os Linux 3.2.0-48 virtual x86_64
My guess is your issue is that you are setting cookie.expires to new Date(Date.now() + (3600 * 60)), which means you want your sessions to expire 3.6 minutes after your server started up, and after those 3.6 minutes have gone by, the Redis SET is now a negative TTL since that date is now in the past?
@dougwilson So, if I set maxAge to an hour the session should automatically update correct?
The documentation isn't very clear around how this works.
Hi @mavrick I'm not 100% sure I understand your question, and of course PRs to improve the docs are super welcome 馃憤 but from what I think you're saying is that the answer is yes.
I want to use passport-local to set a user on the current session for example. If the user is active every hour for 6 hours will they stay logged in, or is the session only ever good for 1 hour then it is reset?
I was using expires because I thought the same thing would happen but from your first comment it is clear I should be using maxAge instead. Ideally I want to set the session time to 2 weeks or even never expire until they click logout.
I'd be happy to submit a PR with some updated examples against 'user stories' to help show people real world examples using the library. :)
So the length of the session is determined by the store; the cookie.maxAge only controls the max age of the cookie itself, and that is bumped each time the cookie is set (because, well, the maxAge sets the cookie's Max-Age attribute to the value you specified).
Basically, there is nothing more to cookie.maxAge than what the docs already say:
cookie.maxAge
Specifies the number (in milliseconds) to use when calculating the Expires Set-Cookie attribute. This is done by taking the current server time and adding maxAge milliseconds to the value to calculate an Expires datetime. By default, no maximum age is set.
I see, so if I want to keep the Session Store persistent do I just need the cookie.maxAge or do I need to also set resave:true or rolling:true.
Historically I've been setting them all to true
{
saveUninitialized: true,
resave: true,
rolling: true,
}
Thanks a lot for your help so far as well! :)
So each session store module can manage the session lifetimes however they wish; there are so many stores I don't really know how they all decide to retain the session. All the options for this module have to do with the management of the cookie itself and just asking the store to load / save an object however it pleases.
Resave forces the session to be saved back to the session store, even if the session was never modified during the request. Depending on your store this may be necessary, but it can also create race conditions where a client makes two parallel requests to your server and changes made to the session in one request may get overwritten when the other request ends, even if it made no changes (this behavior also depends on what store you're using).
How do you know if this is necessary for your store? The best way to know is to check with your store if it implements the touch method. If it does, then you can safely set resave: false. If it does not implement the touch method and your store sets an expiration date on stored sessions, then you likely need resave: true.
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.
And rolling forces a session identifier cookie to be set on every response, instead of only the responses in which the session data was modified. True / false depends on your needs.
I @mavrick I hope I was able to answer all your questions since I haven't heard anything further :)
Thanks @dougwilson for your help mate. I still haven't found the best configuration for what I'm after but I just need to do some more testing on my end to find what works best for my scenario as you suggested.
Cheers
Hi @mavrick . I'm currently running into this same issue. Were you able to find a configuration that worked for you?
Most helpful comment
Hi @mavrick . I'm currently running into this same issue. Were you able to find a configuration that worked for you?