Cannot read property 'connect.sid' of undefined at Layer.session - ExpressJS session - node.js

I am having problems using sessions in ExpressJS 4.
I have tried adding session both in server.js (where I set my app's configurations) and in routes.js (where I define my routes). This is what I keep getting:
TypeError: Cannot read property 'connect.sid' of undefined at Layer.session [as handle]
(/Users/larissaleite/Documents/Routing/node_modules/express-session/index.js:115:32) at trim_prefix
(/Users/larissaleite/Documents/Routing/node_modules/express/lib/router/index.js:226:17) at c
(/Users/larissaleite/Documents/Routing/node_modules/express/lib/router/index.js:198:9) at
Function.proto.process_params
(/Users/larissaleite/Documents/Routing/node_modules/express/lib/router/index.js:251:12) at next
(/Users/larissaleite/Documents/Routing/node_modules/express/lib/router/index.js:189:19) at
Layer.expressInit [as handle]
(/Users/larissaleite/Documents/Routing/node_modules/express/lib/middleware/init.js:23:5) at
trim_prefix (/Users/larissaleite/Documents/Routing/node_modules/express/lib/router/index.js:226:17)
at c (/Users/larissaleite/Documents/Routing/node_modules/express/lib/router/index.js:198:9) at
Function.proto.process_params
(/Users/larissaleite/Documents/Routing/node_modules/express/lib/router/index.js:251:12) at next
(/Users/larissaleite/Documents/Routing/node_modules/express/lib/router/index.js:189:19)
I defined the session like this (server.js):
var express = require('express');
var app = express(); // create app with express
var connect = require('connect');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var passport = require('passport');
var session = require('express-session');
connect()
.use(cookieParser('appsecret'))
.use(function(req, res, next){
res.end(JSON.stringify(req.cookies));
});
app.use(session({ secret: 'appsecret', saveUninitialized: true, cookie: { secure: true, maxAge: new Date(Date.now() + 3600000) }, key:'connect.sid' }));
I've also tried removing the key.
When trying to define the session in routes.js, it was like this:
app.use(session({ secret: 'appsecret', saveUninitialized: true, cookie: { secure: true, maxAge: new Date(Date.now() + 3600000) }, key:'connect.sid' }));
app.use(passport.initialize());
app.use(passport.session());

Remove connect all together. Express 4 was a big overhaul that removed connect as a dependency. remove all parts that require / call connect. Also update all your dependencies.
Per the express-session middleware module's docs:
name - cookie name (formerly known as key). (default: 'connect.sid')
Don't pass it anything and it will use the express sid. I've copied your code and tested it without connect and I'm not getting those errors. Also, I've added the resave key to the session config object to mute the deprecated warnings (if you're running the latest express 4 version).
var express = require('express');
var app = express(); // create app with express
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var passport = require('passport');
var session = require('express-session');
app.use(session({
secret: 'appsecret',
resave: false,
saveUninitialized: true,
cookie: {
secure: true,
maxAge: new Date(Date.now() + 3600000)
}
}));
app.listen(1234);

First of all update your node version to latest version :
sudo npm cache clean -f
sudo npm install -g n
sudo n stable
Update all dependence packages :
npm i -g npm-check-updates
ncu -u
npm install
If required
npm audit fix

Related

ExpressJS session save in cookie

I want create session cookie for track user in site. For this purposes I use "express-session" middleware:
var express = require('express');
var session = require('express-session');
app.use(session({
name: 'cookie',
secret: 'my express secret',
saveUninitialized: true,
resave: true,
cookie: {}
}));
But after NodeJS restart cookie loosing. I can't find cookie session storage like as "Compatible Session Stores". I don't want using database to save sessions, I want configure "express-session" to store all data to cookies. Is it possible?
You can use cookie-session.
To install: npm install cookie-session --save
And include in your app file, for example:
var cookieSession = require("cookie-session");
app.use(cookieSession({
name: "session",
keys: ["key-1","key-2"]
}));

How to configure express and passport with multiple sessions

I need to implement a HTTP server which supports separate session handling with passport. The reason is that I need authentication for 2 entities: my customers (accounts) and their customers (users) and my idea was to use an own secure "space" for that: own session middleware, different session properties, own passport instance.
It's working fine if I just use a session store for the accounts but not for users with this code:
const express = require('express')
const session = require('express-session')
const Passport = require('passport').Passport
const userPassport = new Passport()
const accountPassport = new Passport()
// add passport strategies
const app = express()
app.use(session({
secret: config.session.secret,
//store: accountSessionStore,
resave: true,
saveUninitialized: true,
}))
app.use(accountPassport.initialize({ userProperty: 'account' }))
app.use(accountPassport.session())
app.use(userPassport.initialize({ userProperty: 'user' }))
As soon I add this line app.use(userPassport.session()) at the end it breaks: login flow for accounts doesn't work anymore. It seems that express session middleware cannot handle multiple passport instances and the last call is overwriting the instance.
Wrapping the accounts and customers into an own instance like this:
const app1 = express()
// register stuff for accounts
const app2 = express()
// register stuff for users
const rootApp = express()
rootApp.use(app1)
rootApp.use(app2)
didn't work and using an own HTTP server (and an additional port) seems a bit overkill.
I think passport attaches its instance to request upon initialization, therefore it makes sense that you observe that kind of behavior.
I had similar task and I solved it by creating two instances of Passport and two routers (express.js 4.x).
Then you can configure each session separately and attach different passports to different routes.
Example in coffee script, hope that will give you a clue:
#
# Apps
#
app = express()
adminApp = express()
#
# Routers
#
apiRouter = express.Router()
adminRouter = express.Router()
#
# Authentication
#
apiPassport = new Passport()
adminPassport = new Passport()
#
# Add API auth strategies
#
apiPassport.use new AnonymousStrategy()
adminPassport.use new new TwitterStrategy # ...
adminPassport.serializeUser (user, done) ->
done null, user.id
return
adminPassport.deserializeUser (id, done) ->
done null, id: id
return
#
# Configure session
#
app.use '/api/v1/auth*', session({
name: 'sid',
saveUninitialized: false,
resave: false,
secret: process.env.SESSION_SECRET || 'keyboard cat',
store: new MongoStore(mongooseConnection: mongoose.connection)
})
adminApp.use session({
name: 'admin.sid',
saveUninitialized: false,
resave: false,
secret: process.env.SESSION_SECRET || 'keyboard cat',
store: new MongoStore(mongooseConnection: mongoose.connection)
})
#
# Configure passport middleware
#
app.use '/api*', apiPassport.initialize()
app.use '/api*', apiPassport.session()
adminApp.use adminPassport.initialize()
adminApp.use adminPassport.session()
#
# Mount apps and routers
#
adminApp.use adminRouter
app.use '/api/v1/', apiRouter
app.use '/admin/', adminApp

Can we store session in Database?

Can we store session in database Mysql not in memory using passport module.
I am using nodejs, express and mysql
Thanks
Passport module doesn't provide sessions to your application, it uses connect or express session.
connect/express sessions may (and should!) be persistent and there are plenty of session stores available on npm.
With a quick search I found two implementations of connect/express mysql session store:
connect-mysql
express-mysql-session
Just take any one of them and use as your session store with express-session (or conncect.session):
var express = require('express');
var session = require('express-session');
var SessionStore = require('express-mysql-session')
var app = express();
var sessionStore = new SessionStore(/*options*/);
app.use(session({
key: 'session_cookie_name',
secret: 'session_cookie_secret',
store: sessionStore,
resave: true,
saveUninitialized: true
}))

Best Session Storage Middleware for Express + PostgreSQL

I'm looking for sessionstore for production app because I have error message:
Warning: connect.session() MemoryStore is not designed for a
production environment, as it will leak memory, and will not scale
past a single process
My code:
var express = require('express');
var ECT = require('ect');
var cookieParser = require('cookie-parser');
var compress = require('compression');
var session = require('express-session');
var bodyParser = require('body-parser');
var _ = require('lodash');
var passport = require('passport');
var expressValidator = require('express-validator');
var connectAssets = require('connect-assets');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.use(methodOverride());
app.use(cookieParser());
app.use(session({
resave: true,
saveUninitialized: true,
secret: secrets.sessionSecret,
}));
app.use(passport.initialize());
app.use(passport.session());
var app = module.exports = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(app.get('port'), function() {
console.log('Express server listening on port %d in %s mode', app.get('port'), app.get('env'));
});
module.exports = app;
I don't know what is the best solution for my production app. I'm using sequelize as ORM with PostgreSQL.
I will be very grateful with any opinion.
Though an answer has been accepted, I think a more elaborated answer is in order, so that people who actually want to use Express with PostgreSQL for consistent session storage can have a proper reference.
Express has the session module to handle the sessions though it defaults to in-memory storage that is suitable for development stages but not for production
Warning The default server-side session storage, MemoryStore, is purposely not designed for a production environment. It will leak memory under most conditions, does not scale past a single process, and is meant for debugging and developing.
So for PostgreSQL there is a dedicated simple connector called connect pg simple
Once you import the connect-pg-simple you . need to pass it the session import like this:
const session = require('express-session')
const pgSession = require('connect-pg-simple')(session)
When you add the session as middleware you'll have to pass it its settings
app.use(session(sessionConfig))
and in your sessionConfig, this would be where you set all your session parameters you need to add a store option that would look like this (adding the full set of options though for the matter at hand just note the store option):
const sessionConfig = {
store: new pgSession({
pool: sessionDBaccess,
tableName: 'session'
}),
name: 'SID',
secret: randomString.generate({
length: 14,
charset: 'alphanumeric'
}),
resave: false,
saveUninitialized: true,
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 7,
aameSite: true,
secure: false // ENABLE ONLY ON HTTPS
}}
The new instance of pgSesision takes two options, the pool which is the config setup to access the PostgreSQL DB and the table name.
The DB connection setting should look like this:
const sessionDBaccess = new sessionPool({
user: DB_USER,
password: DB_PASS,
host: DB_HOST,
port: DB_PORT,
database: DB_NAME})
Also note that the session pool must be initiated:
const sessionPool = require('pg').Pool
I got it working with connect-pg-simple.
Create a session table with the provided table.sql, and pass in a connection string or an object.
If you have just to store session you can use redis or maybe mongoDB if you want persistence.

session is undefined using sesssion.socket.io-express4

I'm working on a NodeJs with the following modules:
express 4.9.8
express-session 1.9.3
socket.io 1.2.1
session.socket.io-express4 0.0.3
I'm trying to get a session from session.socket.io-express4 in app.js using the following code:
first the init of the all thing in app.js:
var server = app.listen(3000, function() {
debug('Express server listening on port ' + server.address().port);
});
var io = require('socket.io')(server);
var sessionstore = require('sessionstore');
var sessionStore = sessionstore.createSessionStore();
var cookieParserVar = cookieParser('bingo');
app.use(session({
secret: 'bingo',
cookie: {httpOnly: true, secure: true, maxAge: new Date(Date.now() + 3600000)},
store: sessionStore,
resave: true,
saveUninitialized: true
}));
var SessionSockets = require('session.socket.io-express4');
sessionSockets = new SessionSockets(io, sessionStore, cookieParserVar);
require('./models/socket.js')(sessionSockets);
my socket.js:
function handleSocket(sessionSockets) {
sessionSockets.on('connection', function (err, socket, session) {
console.log("session : " + session);
});
}
module.exports = handleSocket;
the problem is that session is undefined. any ideas ?
update
so i tried using socket.io-sessions instead.
this is my code:
var sessionstore = require('sessionstore');
var sessionStore = sessionstore.createSessionStore();
var cookieParserVar = cookieParser();
app.use(session({
secret: 'bingo',
key: 'express.sid',
store: sessionStore,
resave: true,
saveUninitialized: true
}));
io.set("authorization", socketIoSessions({
key: 'express.sid', //the cookie where express (or connect) stores its session id.
secret: 'bingo', //the session secret to parse the cookie
store: sessionStore //the session store that express uses
}));
require('./models/socket.js')(io);
and my models/socket.js file includes:
function handleSocket(sock) {
sock.on('connection',function(socket)
{
socket.handshake.getSession(function (err, session) {
console.log("HERHERHEHREHREHRHEHERHERHRHERHERHEHREHREHREHR");
console.log(session);
console.log(err);
});
require('../commands/echo.js')(sock);
});
}
module.exports = handleSocket;
this is the error that I get:
/mnt/storage/home/ufk/work-projects/bingo/server/bingo-server/models/socket.js:8
socket.handshake.getSession(function (err, session) {
^
TypeError: Object #<Object> has no method 'getSession'
at Namespace.<anonymous> (/mnt/storage/home/ufk/work-projects/bingo/server/bingo-server/models/socket.js:8:34)
at Namespace.emit (events.js:95:17)
at Namespace.emit (/mnt/storage/home/ufk/work-projects/bingo/server/bingo-server/node_modules/socket.io/lib/namespace.js:205:10)
at /mnt/storage/home/ufk/work-projects/bingo/server/bingo-server/node_modules/socket.io/lib/namespace.js:172:14
at process._tickCallback (node.js:419:13)
what am i missing ?
last update
socket.io-session works as expected.
the only thing that i needed to change is the authorization callback in order for it to be compatible with socket.io-1.0 i did the following:
io.use(function (socket, next) {
var handshakeData = socket.handshake;
ioSession(cookieParser(config.app.session_key), sessionStore)(handshakeData, next);
}
);
update
The explanation of the issue from the original answer is still all relevant, but the fix is much simpler (and more secure). Just use socket.io-session instead. The session.socket.io-express4 module is only necessary if you're using the connect version of cookieParser which doesn't have the same signature handling as the newer cookie-parser does.
original answer
This is due to a bug in sesssion.socket.io-express4 when using both a cookie-parser secret and an express-session secret. What's happening is sesssion.socket.io-express4 is trying to strip the signing off of the connect.sid cookie. You can see that here:
if(handshake.cookies && handshake.cookies[key]) handshake.cookies[key] = (handshake.cookies[key].match(/\:(.*)\./) || []).pop();
The signed cookie looks like this s:<value>.<signature>, and the regex selects anything between : and . which would be the value of the signed cookie. The problem is, cookie-parser will remove the signature itself if you pass in a secret. That means that session.socket.io-express4 is expecting s:<value>.<signature> but is receiving <value> instead so the regex returns undefined. To work around this you could omit the secret from cookie-parser.
I have submitted a pull request to session.socket.io-express4 with a fix for this bug so you have to use a cookie-parser with the same secret as the express-session.
tl;dr
Don't supply a secret to the cookie-parser. The following should work as you expect:
var server = app.listen(3000, function() {
debug('Express server listening on port ' + server.address().port);
});
var io = require('socket.io')(server);
var sessionstore = require('sessionstore');
var sessionStore = sessionstore.createSessionStore();
var cookieParserVar = cookieParser();
app.use(session({
secret: 'bingo',
store: sessionStore,
resave: true,
saveUninitialized: true
}));
var SessionSockets = require('session.socket.io-express4');
sessionSockets = new SessionSockets(io, sessionStore, cookieParserVar);
require('./models/socket.js')(sessionSockets);

Resources