Passport: Passportjs and node-client-sessions

Created on 24 Nov 2013  路  8Comments  路  Source: jaredhanson/passport

Hello,
I am trying to use passportjs with node-client-sessions [https://github.com/mozilla/node-client-sessions ].
But it seems like it does not work properly. I read some thread with similar issues on node-client-sessions. https://github.com/mozilla/node-client-sessions/issues/42

Following that issue. I made following change in initialize.js middleware of passport.

https://gist.github.com/yalamber/bcbe24a5413d692be412

It is simply reassigining passport.session to req.session.

It does work now with node-client-sessions. Is it ok to make this work this way? Should I be careful implementing this patch?

Most helpful comment

I know this is closed, but I came across it and it didn't provide the answer I needed, so I will provide it below in hopes that it helps someone else (this is one of the top Google results for searches like "passport with client-sessions").

In order to get Passport working with node-client-sessions, you need to do 2 things:

  • in your client-sessions config, make sure cookieName is set to user. So my config looks like this:
app.use(clientSessions({
  cookieName: 'user', // important
  secret: 'itsasecretduh',
  duration: 30 * 60 * 1000, // 30 minutes
  activeDuration: 5 * 60 * 1000, // 5 minutes
}));
  • the second thing I noticed was a problem when trying to logout. Passport will set the request property (user in this case) to null, which node-client-sessions doesn't like. When that happens, I get the error: [TypeError: cannot set client-session to non-object]. To combat this, I manually logout via this code:
export default function logout(req, res) {
  // I couldn't get anything to work except this
  // set the cookie to an expiration time of now, this way it expires right away
  res.cookie('user', '', { expires: new Date() });
  res.json(null);
}

To check if the user is authenticated, what I had been doing was

if (req.user && req.user.id) {
// i'm authenticated
}

Note: this is with the following relevant dependencies:

"passport": "^0.3.2",
"passport-facebook": "^2.0.0",
"passport-local": "^1.0.0",
"express": "^4.13.3",
"client-sessions": "^0.7.0",

All 8 comments

Hi,

Was this one fixed? If so, do we have any available example of how to use node-client-sessions with passport?

Thx,
Edu谩rd

Hello,
No changes were needed to the passportjs and client sessions with latest versions. They both are compatible.

for me it's not working... not sure why
when i use the following it does not work

app.use(clientSessions({
  // cookieName: 'sid', // (aka session id) - name on client side
  // requestKey: 'userId', // req.userId will be available on req object
  secret: process.env.SESSION_COOKIE_SECRET, // to sign + encrypt the cookie
  duration: monthDuration, // 30 days session
  activeDuration: monthDuration, // extend the session on each visit
  cookie: {
    secure: false, // when true, cookie will only be sent over SSL. use key 'secureProxy' instead if you handle SSL not in your node process
  },
}));

but when i use

app.use(require('cookie-parser')());
app.use(require('express-session')({
  resave: true,
  saveUninitialized: true,
  secret: 'keyboard cat',
}));

it does work

@eyalw you might be interested in this info

https://github.com/expressjs/cookie-session/issues/52#issuecomment-174142222

expresss-session is server side sessions...client-session is client side sessions

I know this is closed, but I came across it and it didn't provide the answer I needed, so I will provide it below in hopes that it helps someone else (this is one of the top Google results for searches like "passport with client-sessions").

In order to get Passport working with node-client-sessions, you need to do 2 things:

  • in your client-sessions config, make sure cookieName is set to user. So my config looks like this:
app.use(clientSessions({
  cookieName: 'user', // important
  secret: 'itsasecretduh',
  duration: 30 * 60 * 1000, // 30 minutes
  activeDuration: 5 * 60 * 1000, // 5 minutes
}));
  • the second thing I noticed was a problem when trying to logout. Passport will set the request property (user in this case) to null, which node-client-sessions doesn't like. When that happens, I get the error: [TypeError: cannot set client-session to non-object]. To combat this, I manually logout via this code:
export default function logout(req, res) {
  // I couldn't get anything to work except this
  // set the cookie to an expiration time of now, this way it expires right away
  res.cookie('user', '', { expires: new Date() });
  res.json(null);
}

To check if the user is authenticated, what I had been doing was

if (req.user && req.user.id) {
// i'm authenticated
}

Note: this is with the following relevant dependencies:

"passport": "^0.3.2",
"passport-facebook": "^2.0.0",
"passport-local": "^1.0.0",
"express": "^4.13.3",
"client-sessions": "^0.7.0",

@ingshtrom that may work, but I have had success just using cookie-session for client sessions, as a drop in replacement for express-session, like so:

var cookieSession = require('cookie-session');

app.use(cookieSession({
    name: 'sc-admin-session',
    secret: 'feyenoord5'
}));

@ORESoftware are you manually setting req['sc-admin-session'] in your code, or is passport setting that automatically for you? If Passport is doing it, how do you tell it to do that?

I guess that is the difference between our two approaches. You _seem_ to be managing two sessions, passport and client-sessions--correct me if I am wrong. I am attempting to get both of them to play nice so that I only need to mess with a single session.

I'm not an expert on Passport, but @ingshtrom's response above makes me nervous, and I'd encourage others to do more research before following their solution. This is my understanding:

Normally, Passport automatically sets req.user after the user has been authorized by a strategy or by restoring an active session. Passport _only_ sets req.user after a user has been authorized, which is why you can do stuff like const isAuthorized = () => !!req.user;. Setting req.user yourself (via client-sessions) means that _you_ (and not Passport) are now making that decision.

It is plausible that this approach works, and it's plausible that it happens to be secure, but this would be coincidental and fragile. You should not be setting req.user yourself.

Try this:

const config = require('config');
const express = require('express');
const passport = require('passport');
const sessions = require('client-sessions');

const app = express();

// passport expects the cookie to be named "session"
app.use(sessions({
    secret: config.get('SESSION_SECRET'), // extremely secret
    cookieName: 'session', // automatically used by passport sessions
}));

// config passport
passport.use(SomeStrategy);
passport.serializeUser((user, done) => done(null, JSON.stringify(user)));
passport.deserializeUser((userStr, done) => done(null, JSON.parse(userStr)));
app.use(passport.initialize());
app.use(passport.session());

Hope this is useful.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wongeun picture wongeun  路  4Comments

callumacrae picture callumacrae  路  5Comments

Manubi picture Manubi  路  6Comments

apowers313 picture apowers313  路  6Comments

franckl picture franckl  路  5Comments