Mongoose and connect-mongo - node.js

I am using mongoose for managing relationships between data and I am trying to use connect-mongo to store specific sessions in the database.
It looks like that we need to connect twice to the db, one with mongoose and another one with connect-mongo.
I am using the following code to initialise a connection for mongoose
await mongoose.connect(this._connectionUrl, this._connectionOptions);
Initialising a new store every time (not sure if I am correct regarding code initialisation).
app.use(session({
// secret: config.sessionSecretKey,
secret: "secretkey",
resave: true,
saveUninitialized: true,
cookie: { maxAge: 19 * 60000 }, // store for 19 minutes
store: MongoStore.create({
mongoUrl: this._connectionUrl,
mongoOptions: this._connectionOptions // See below for details
})
}))
Is there any way that I can pass the connection from mongoose to mongo-connect Store?

i'm lookin for a solution too and just read this on the "migration guide" of connect-mongo
For the options, you should make the following changes:
Change url to mongoUrl Change collection to collectionName if you are
using it Keep clientPromise if you are using it mongooseConnection has
been removed. Please update your application code to use either
mongoUrl, client or clientPromise To reuse an existing mongoose
connection retreive the mongoDb driver from you mongoose connection
using Connection.prototype.getClient() and pass it to the store in the
client-option. Remove fallbackMemory option and if you are using it,
and there's this example https://github.com/jdesboeufs/connect-mongo/blob/master/example/mongoose.js

I've just been digging through the docs and through a few other SO responses. I've found this works really well with the new version of connect-mongo.
const session = require('express-session');
const MongoStore = require('connect-mongo');
app.use(
session({
secret: "secretkey",
resave: true,
saveUninitialized: true,
cookie: { maxAge: 19 * 60000 }, // store for 19 minutes
store: MongoStore.create({
client: mongoose.connection.getClient()
})
})
);
It is recommended by the devs for connect-mongo to utilise the connection object for mongoose to retrieve the client to ride the same connection so you don't have to setup two separate connections. This seems like a really clean way to do it but comment if you spot anything off!
This was pulled from the bottom of the connect-mongo migration guide here

Related

Keep user sessions logged in on Node.js server restart

I am using express-session for a login system for users on my Node.js web application. My issue is that every time I make an update and restart the Node.js server, all the users are logged off which is not ideal behaviour (there are multiple users logged on via the local network and I would like to not have to log them back on each time there is a restart).
From my understanding I could use something such as connect-pg-simple (for reference I am using a postgres database with my node web app) to keep users logged in on server restart but I am unsure of how to implement this.
I know it would be something along the lines of:
app.use(session({
store: new (require('connect-pg-simple')(session))({
// Insert connect-pg-simple options here
}),
secret: 'secret',
resave: false,
saveUninitialized: true
}));
But I do not know what options to use or how to save the users session even on server restart.
Yes you are on the right track.
Open your database and create a table named session. See: https://github.com/voxpelli/node-connect-pg-simple/blob/HEAD/table.sql
Add the connect-pg-simple code like you posted
Pass the postgres pool you are using from node-pg.
const session = require('express-session')
const PGSessionStore = require('connect-pg-simple')(session)
const pg = require('pg')
const pool = new pg.Pool({
user: process.env.PG_USERNAME,
host: process.env.PG_HOST,
database: process.env.PG_DATABASE,
password: process.env.PG_PASSWORD,
port: process.env.PG_PORT
})
app.use(session({
store: new PGSessionStore({
pool: pool,
tableName: 'session'
}),
secret: process.env.COOKIE_SECRET,
cookie: {
secure: false,
httpOnly: true,
sameSite: true,
maxAge: 24 * 60 * 60 * 1000
},
saveUninitialized: true,
resave: false
}))
Your session is stored on the app runtime, so on refresh, it resets back every other data it might be holding at runtime on server restart

How to call 'store' commands with 'express-session'?

I am using Node.js/Express with the 'express-session' module for session management. My setup is as follows:
var session = require('express-session');
var MemoryStore = require('memorystore')(session)
const express = require('express');
const app = express();
app.use(session({
cookie: { maxAge: 86400000 },
store: new MemoryStore({
checkPeriod: 86400000 // prune expired entries every 24h
}),
resave: false,
saveUninitialized: false,
unset: 'destroy',
secret: process.env.COOKIE_SECRET
}))
My question is simple...how do I call the 'store' commands (for example ".all", ".destroy", ".length", etc)...? I have attempted at least the following:
session.store.all(function(error, len) {console.log("EXECUTED MEMORYSTORE LIST: ");})
MemoryStore.all(function(error, len) {console.log("EXECUTED MEMORYSTORE LIST: ");})
store.all(function(error, len) {console.log("EXECUTED MEMORYSTORE LIST: ");})
...Nothing of which works...I always get a "not a function" error thrown. I would like to access these commands to enable cycling through the sessions in the store, deleting as necessary, and other misc tasks.
Any advice on how to access these 'store commands' would be greatly appreciated. I thank you in advance.
If you want access to the MemoryStore interface for that module, then you just have to save the instance to your own variable:
const memoryStore = new MemoryStore({
checkPeriod: 86400000 // prune expired entries every 24h
});
app.use(session({
cookie: { maxAge: 86400000 },
store: memoryStore,
resave: false,
saveUninitialized: false,
unset: 'destroy',
secret: process.env.COOKIE_SECRET
}));
Now, you have access to the instance of the memoryStore and you can access whatever methods it has. You can see what methods it offers in the code here. It's implementation is really just in service of the express-session store interface - it is not meant as a separately accessible database, but you can call the methods from the express-session store interface.
Keep in mind that the tasks you ask about are better served by using a session store that is a real database and has a real database interface. Then, you can use the regular database interface to access previously store session data.

How to access connect-mongodb-session collection

Hello I am fairly new to connect-mongodb-session library so I would love to know how I can access the collection of user sessions so that I can have a code logic to check if user session has expired so that I can remove it from collection.
I know with connect-mongo:
I can set it up like this below to check each hour for expired sessions and it automatically removes the expired sessions
const sessionStore = new MongoStore({
db: 'myappsession',
clear_interval: 3600
});
But now with connect-mongodb-session there's no prop 'clear_interval'
This is how my connect-mongodb-session store is made:
const mongoStore = MongoStore(expressSession);
const store = new mongoStore({
collection: "userSessions",
uri: process.env.mongoURI,
expires: 10 * 1000 * 24 * 60 * 60,
});
So when things are like this how can I go about this
var store=mongoDbStore({
uri:connectionString,
collection:"mySessions"
})
app.use(
session({
secret:key,
resave: true,
saveUninitialized:false,
cookie:{
maxAge:3600000
},
store:store
})
)
You can give a maxAge like above. This session will be terminated.

Express 4 Sessions not persisting when restarting server

I have an Express 4 app setup to have sessions.
// Sessions
app.use(cookieParser());
app.use(session({ secret: "some-secret" }));
// Signup
app.post("/signup", function (req, res) {
create_user(req.body.user, function (err, user_id) {
req.session.user_id = user_id;
res.redirect("/admin");
});
});
When I submit the form, it saves the user_id to the req.session. However, when I restart the server, the session is gone.
Why isn't it persisting? Am I missing some configuration?
The default session store for express-session is MemoryStore, which as the name suggests, stores sessions in memory only. If you need persistence, there are many session stores available for Express. Some examples:
Cookie store
Redis store
MongoDB store
CouchDB store
Riak store
memcached store
leveldb store
MySQL store
PostgreSQL store
Firebase store
For a updated and more complete list visit Compatible Session Stores.
#mscdex answer is great but in case you are looking for code samples. Here is one with connect-mongo which should work fine if you mongodb and mongoose.
Install the package:
npm i connect-mongo
require the package:
const session = require('express-session'); // You must have express-sessions installed
const MongoStore = require('connect-mongo')(session)
Now configure the session:
app.use(
session({
secret: "mysecrets",
resave: false,
saveUninitialized: false,
store: new MongoStore({
mongooseConnection: mongoose.connection,
ttl: 14 * 24 * 60 * 60
}),
})
);
Again this assumes you are using mongoose and have the connection configured.
If you did everything right, it should work just fine.

Node.js + express.js + passport.js : stay authenticated between server restart

I use passport.js to handle auth on my nodejs + express.js application. I setup a LocalStrategy to take users from mongodb
My problems is that users have to re-authenticate when I restart my node server. This is a problem as I am actively developing it and don't wan't to login at every restart... (+ I use node supervisor)
Here is my app setup :
app.configure(function(){
app.use('/static', express.static(__dirname + '/static'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({secret:'something'}));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
});
And session serializing setup :
passport.serializeUser(function(user, done) {
done(null, user.email);
});
passport.deserializeUser(function(email, done) {
User.findOne({email:email}, function(err, user) {
done(err, user);
});
});
I tried the solution given on a blog (removed the link as it does not exist any more) using connect-mongodb without success
app.use(express.session({
secret:'something else',
cookie: {maxAge: 60000 * 60 * 24 * 30}, // 30 days
store: MongoDBStore({
db: mongoose.connection.db
})
}));
EDIT additional problem : only one connection should be made (use of one connexion limited mongohq free service)
EDIT 2 solution (as an edition as I my reputation is to low to answer my question by now
Here is the solution I finally found, using mongoose initiated connection
app.use(express.session({
secret:'awesome unicorns',
maxAge: new Date(Date.now() + 3600000),
store: new MongoStore(
{db:mongoose.connection.db},
function(err){
console.log(err || 'connect-mongodb setup ok');
})
}));
There's an opensource called connect-mongo that does exactly what you need - persists the session data in mongodb
usage example (with a reuse of mongoose opened connection) :
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/sess');
app.use(express.session({
secret:'secret',
maxAge: new Date(Date.now() + 3600000),
store: new MongoStore(
// Following lines of code doesn't work
// with the connect-mongo version 1.2.1(2016-06-20).
// {db:mongoose.connection.db},
// function(err){
// console.log(err || 'connect-mongodb setup ok');
// }
{mongooseConnection:mongoose.connection}
)
}));
you can read more about it here: https://github.com/kcbanner/connect-mongo
i use connect-mongo like so:
var MongoStore = require('connect-mongo');
var sess_conf = {
db: {
db: mydb,
host: localhost,
collection: 'usersessions' // optional, default: sessions
},
secret: 'ioudrhgowiehgio'
};
app.use(express.session({
secret: sess_conf.secret,
maxAge: new Date(Date.now() + 3600000),
store: new MongoStore(sess_conf.db)
}));
[...]
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
This is because you use MemoryStore (default) for sessions. Look at this code from memory.js (part of Connect framework):
var MemoryStore = module.exports = function MemoryStore() {
this.sessions = {};
};
and this snippet from session.js (Express)
function session(options){
/* some code */
, store = options.store || new MemoryStore
/* some code */
}
Now you should understand that every server restart resets the MemoryStore. In order to keep the data you have to use some other session store. You can even write your own (shouldn't be too difficult), although Redis (see this library) might be a good choice (and it is well supported by Express).
// EDIT
According to the Connect documentation it is enough for you if you implement get, set and destroy methods. The following code should work:
customStore = {
get : function(sid, callback) {
// custom code, for example calling MongoDb
},
set : function(sid, session, callback) {
// custom code
},
destroy : function(sid, callback) {
// custom code
}
}
app.use(express.session({
store: customStore
}));
You just need to implement calling MongoDb (or any other Db although I still recommend using nonpermament one like Redis) for storing session data. Also read the source code of other implementations to grab the idea.
This is probably obvious to experienced node users but it caught me out:
You need to configure the node session - e.g.
app.use(session({secret: "this_is_secret", store: ...}));
before initializing the passport session - e.g.
app.use(passport.initialize());
app.use(passport.session());
If you call passport.session() first it won't work (and it won't warn you). I thought the problem was with the serialize/deserialize user functions and wasted hours.
I'm using mongoose, I tried the code presented in the answers above and it didn't work for me. I got this error when I did:
Error: db object already connecting, open cannot be called multiple times
However, this works for me:
app.use(express.session({
secret:'secret',
maxAge: new Date(Date.now() + 3600000),
store: new MongoStore({mongoose_connection:mongoose.connection})
}))
Note: If you don't have MongoStore for whatever reason, you need to do:
npm install connect-mongo --save
then:
var MongoStore = require('connect-mongo')(express)
What I ended up doing:
var expressSession = require('express-session');
var redisClient = require('redis').createClient();
var RedisStore = require('connect-redis')(expressSession);
...
app.use(expressSession({
resave: true,
saveUninitialized: true,
key: config.session.key,
secret: config.session.secret,
store: new RedisStore({
client: redisClient,
host: config.db.host,
port: config.db.port,
prefix: 'my-app_',
disableTTL: true
})
}));
Works for me.
You need to change the store you are using for your sessions. The default one 'MemoryStore' does not continue to store the session when you're application stops. Check out express-session on github to find out more about what other stores there are like the mongo one. (Can't remember the name)

Resources