timaschew timaschew - 2 months ago 25
Node.js Question

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.

Answer

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