I have a Web application using express and authenticate by passport local strategy and store session with connect-mongo. The app work fine on localhost, but when I deploy it with iisnode, its behavior becomes abnormal. After the first User A logged in, I try log in with User B account on a different browser (I tried incognition mode, different machine, different network, etc...). Then I come to the browser of User A, I realize it become the same session as user B.
So it mean all logged user will use the last logged user session. I thought it was some misconfigure but I cant figure it out, I try revert to a previous commit and still have the same issue. I check the cookies in User A browser and the cookies has been change to User B Session ID
Here is my main app code
const app = express();
app.use(
helmet({
contentSecurityPolicy: false,
})
);
app.disable("x-powered-by");
app.use(useragent.express());
app.set("trust proxy", true);
app.set("trust proxy", function () {
return true;
});
if (process.env.NODE_ENV !== "production") {
app.use(logger("dev"));
} else {
app.use(logger("common"));
}
// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "pug");
app.use(express.json({ limit: "100mb", extended: true }));
app.use(express.urlencoded({ limit: "200mb", extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public")));
mongoose
.connect(process.env.MONGO_URI2, {
useNewUrlParser: true,
useUnifiedTopology: true,
autoIndex: false,
})
.then(() => console.log("Connect to MongoDB success"))
.catch((err) => {
console.log(err);
// process.exit();
});
app.use(
session({
name: "definitelyNotSID",
secret: "some super secret",
clear_interval: 60 * 60,
resave: false,
saveUninitialized: false,
cookie: { maxAge: 14 * 24 * 60 * 60 * 1000 },
store: MongoStore.create({
client: mongoose.connection.getClient(),
}),
})
);
app.use(passport.initialize());
app.use(passport.session());
// refresh session exp time
app.use(function (req, res, next) {
if ("HEAD" == req.method || "OPTIONS" == req.method) return next();
if (req.isAuthenticated()) {
req.session._garbage = Date();
req.session.touch();
}
next();
});
app.use("/", router);
And there are my passport serializeUser and deserializeUser
passport.serializeUser((user, done) => {
console.log("serialize user id", user.id)
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, "-password", (err, user) => {
console.log("deserializeUser username", user.username)
Role.getLevel(user.account_type).then((result) => {
user.user_level = result.level;
done(err, user);
});
});
});
I also have a middleware to restrict access to only logged user:
isLogged: (req, res, next) => {
console.log(req.session)
console.log(req.cookies)
if (req.isAuthenticated()) {
next();
} else {
res.set("location", "/auth/login");
return res.status(301).send();
}
},
Im not sure it was my code problem or IISNode, any help would be appreciated!
After almost two days of digging, I found it. The problem is not in express but IIS. I have some configs to cache .js
and .css
files. But somehow it prevents some requests come to express, and that messed the whole things up.
Eg:
(On the left is IIS log, and the right is iisnode log, the /quan-ly/ GET request didnt pass through)
I simply delete the caching settings and it works again. I hope it help someone occurs the same problem with me.