Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does passport.js require session affinity when deployed on multiple node.js instances

Does passport.js require session affinity when deployed on multiple Node.js instances? When I am employing session affinity the authentication works properly with multiple instances (behind a load balancer). I am using redis as session store. However, when not using session affinity the passport.js is failing with the error given below. With a single instance it always works. Is there any way to make passport.js work without session affinity.

    500 Failed to verify assertion (message: Invalid association handle)

    at Strategy.authenticate.identifier (node_modules/passport-google/node_modules/passport-openid/lib/passport-openid/strategy.js:184:36)
    at _verifyAssertionData (node_modules/passport-google/node_modules/passport-openid/node_modules/openid/openid.js:1053:12)
    at _verifyAssertionAgainstProvider (node_modules/passport-google/node_modules/passport-openid/node_modules/openid/openid.js:1178:14)
    at _checkSignatureUsingAssociation (node_modules/passport-google/node_modules/passport-openid/node_modules/openid/openid.js:1229:14)
    at Object.openid.loadAssociation (node_modules/passport-google/node_modules/passport-openid/node_modules/openid/openid.js:111:5)
    at _checkSignatureUsingAssociation (node_modules/passport-google/node_modules/passport-openid/node_modules/openid/openid.js:1221:10)
    at _checkSignature (node_modules/passport-google/node_modules/passport-openid/node_modules/openid/openid.js:1211:5)
    at _verifyAssertionAgainstProvider (node_modules/passport-google/node_modules/passport-openid/node_modules/openid/openid.js:1174:3)
    at _verifyDiscoveredInformation node_modules/passport-google/node_modules/passport-openid/node_modules/openid/openid.js:1145:16)
    at openid.discover (node_modules/passport-google/node_modules/passport-openid/node_modules/openid/openid.js:668:7)

The code snippet using passport:

app.set('port', process.env.PORT || 8080);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.query());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser()); 
app.use(express.session({ key: 'JSESSIONID', secret: '****', cookie : {httpOnly:false, 
   maxAge: 5*60*1000, path: '/'},
    store: new RedisStore({ prefix: 'sid:', client: redisClient })
                    }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.get('/auth/google', passport.authenticate('google'));
app.get('/auth/google/return', 
      passport.authenticate('google', { successRedirect: '/success',
                                        failureRedirect: '/login' }));

I also have serializeUser and deserializeUser that uses redis store to store/retrieve user object - but this error is happening when the identity provider redirects back to the callback URI. I am deploying my app in AppFog and setting the session affinity using JSESSIONID cookie key (that's how cloudfoundry load balancers work). If I use any other key (that means session affinity is off) then the error is thrown by passport.js.

like image 608
jrajp2184 Avatar asked Jun 24 '13 11:06

jrajp2184


People also ask

How does Nodejs passport work?

Passport is a popular, modular authentication middleware for Node. js applications. With it, authentication can be easily integrated into any Node- and Express-based app. The Passport library provides more than 500 authentication mechanisms, including OAuth, JWT, and simple username and password based authentication.

How does Passport JS handle authorization?

Authorization is performed by calling passport. authorize() . If authorization is granted, the result provided by the strategy's verify callback will be assigned to req.account . The existing login session and req.

What is session in passport JS?

This series of requests and responses, each associated with the same user, is known as a session. HTTP is a stateless protocol, meaning that each request to an application can be understood in isolation - without any context from previous requests.

Is Passport js a middleware?

Passport is an authentication middleware for Node. js which we are going to use for session management.


1 Answers

I think I have fixed it. There is an option: 'stateless' that can be passed to GoogleStrategy. I figured it out by looking at the source: https://github.com/jaredhanson/passport-openid/blob/master/lib/passport-openid/strategy.js. Therefore the GoogleStrategy instantiation must be:

new GoogleStrategy({
   returnURL: BASE + '/auth/google/return',
   realm: BASE + "/",
   stateless: true
}

Thanks to Jared Hanson for implementing such an option! (hopefully it will get documented at the main site).

like image 62
jrajp2184 Avatar answered Sep 21 '22 05:09

jrajp2184