I am developing a web application using NestJS, Passport, express-session, and I've implemented custom session management using Redis (ioredis). I've noticed that the set method in my custom RedisStore is being triggered twice for a single user session creation, and I cannot figure out why this is happening. All other methods are triggered only once.
I have a LocalAuthGuard that extends AuthGuard('local') from @nestjs/passport, which is used for authentication:
import { ExecutionContext, Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {
async canActivate(context: ExecutionContext) {
const result = (await super.canActivate(context)) as boolean;
const request = context.switchToHttp().getRequest();
await super.logIn(request);
return result;
}
}
My session is configured as follows in the bootstrap function:
app.use(
session({
name: 'dekada_session',
store: new RedisStore(redisService),
secret: 'keyboard cat',
resave: false,
saveUninitialized: false,
rolling: false,
cookie: {
maxAge: 3600000,
secure: false,
sameSite: 'lax',
httpOnly: true,
},
}),
);
This is the simplified version of set
set(sid: string, session: SessionData, callback?: (error?: any) => void): void {
console.log('set');
const ttl = 3600;
this.redisService.getClient().setex(`sess:${sid}`, ttl, JSON.stringify(session), (error) => {
callback(error);
});
}
Despite sending only one request from Postman, the set method is logged twice, indicating its being called twice. This happens during the login process, where a session should be created only once. I verified that the serializeUser and deserializeUser methods of Passport are called only once, and the same applies to the canActivate method in my LocalAuthGuard.
That's how console logs are triggered:
- get
- destroy
- set
- [Function: serialized]
- set
After inspecting passport code, found roots of double set invocation.
/lib/sessionmanager.js
This code regenerates the session as a security measure against session fixation attacks by creating a new session ID while preserving session data. After regeneration, it explicitly saves the session again. However, express-session seems to notice the session update and triggers another set operation automatically at the end of the request-response cycle.
While I understand the necessity of session regeneration for security purposes, I'm looking to optimize session handling by eliminating the redundant set call made by express-session. This redundancy seems unnecessary and could potentially impact performance.
Question: Is there a way to configure express-session or Passport to prevent this additional session set operation while still maintaining the integrity and security of the session, especially in the context of preventing session fixation attacks?