expresspassport.jspassport-localiisnodeconnect-mongo

Express passport local always login as the last login session in iisnode


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 enter image description here

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!


Solution

  • 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: Request is missing in log (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.