I am developing a student request management system. I have used node, mysql and express. When a user logged-in he should be redirected to a dashboard.
I am using express-session to manage user sessions.
When a user successfully logged-in, the browser will send a GET request to the dashboard. But before handling the GET request there is a middleware called authChecker to check the session created on a successful login. Although the req.session.user is set inside the /login route, req.session.user is undefined inside the authChecker. Therefore user gets redirected back to login page even he logged-in correctly.
When debugging this issue in VS Code, I found that the req.session.id is changed from /login to authChecker. I think that means req.session object is changed. That’s why req.session.user is undefined inside the authChecker.
OS: Linux Mint 20 Cinnamon
Node version: 14.15.0
npm version: 6.14.9
Browser: Firefox 86.0.1 (64 bit) and Google Chrome 89.0.4389.90 (64 bit)
(Both Firefox and Chrome shows the same error)
N.B: Several friends of mine on Windows and Macs have tried this app on their machines without any problem. So could be this is because of some setting of my computer ?
Server.js
import cookieParser from "cookie-parser";
import express from "express";
import expressMySqlSession from "express-mysql-session";
import expressSession from "express-session";
import createError from "http-errors";
import logger from "morgan";
import mysql from "mysql";
import path from "path";
import socketio from "socket.io";
import {
MYSQL_DATABASE,
MYSQL_HOST,
MYSQL_PASSWORD,
MYSQL_USER,
NODE_ENV,
PORT,
SESS_LIFETIME,
SESS_NAME,
SESS_SECRET,
} from "./config/constants";
import router from "./routes/index";
// MySQL database
const MySQLOptions = {
host: MYSQL_HOST,
user: MYSQL_USER,
password: MYSQL_PASSWORD,
database: MYSQL_DATABASE,
};
const pool = mysql.createPool({ connectionLimit: 10, ...MySQLOptions });
pool.getConnection((err, conn) => {
if (err) throw err;
// Check connection
console.log("Connected to MySQL database");
conn.release();
});
// Express app
const app = express();
// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");
// Options
app.disable("x-powered-by");
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static("public"));
app.use(logger("dev"));
// Session store
const MySQLStore = expressMySqlSession(expressSession);
const sessionStore = new MySQLStore(
{ clearExpired: true, checkExpirationInterval: 600000, ...MySQLOptions },
pool
);
const session = expressSession({
name: SESS_NAME,
secret: SESS_SECRET,
saveUninitialized: false,
resave: false,
store: sessionStore,
cookie: {
sameSite: true,
secure: NODE_ENV === "production",
maxAge: parseInt(SESS_LIFETIME),
},
});
app.use(session);
// Check session
app.use((req, res, next) => {
if (!req.session.user) {
res.clearCookie(SESS_NAME);
}
next();
});
// Start server
const io = socketio(
app.listen(PORT, () =>
console.log(`App running at http://localhost:${PORT}`)
)
);
io.use((socket, next) => {
let req = socket.handshake;
let res = socket.request.res || {};
cookieParser()(req, res, (err) => {
if (err) return next(err);
session(req, res, next);
});
});
// Routing
const {
loginRouter,
logoutRouter,
dashboardRouter,
requestRouter,
replyRouter,
} = router(pool, io);
app.use("/login", loginRouter);
app.use("/logout", logoutRouter);
app.use("/dashboard", dashboardRouter);
app.use("/request", requestRouter);
app.use("/reply", replyRouter);
app.use("*", (req, res) => {
// Default route
res.redirect("/login");
});
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get("env") === "development" ? err : {};
// render the error page
res.status(err.status || 500);
res.render("error");
});
login.js
import express from "express";
import { sessionChecker } from "../util/middleware";
import { sessionizeUser } from "../util/helpers";
import { getUserById } from "../util/database";
const handler = (pool) => {
const loginRouter = express.Router();
// Get request for login page
loginRouter.get("", sessionChecker, (req, res) => {
// Show login page
res.render("login");
});
// Post request for login
loginRouter.post("", sessionChecker, async (req, res) => {
const { userId, password } = req.body;
const user = await getUserById(pool, userId);
if (!user) {
res.redirect("/login");
} else if (!user.validPassword(password)) {
res.redirect("/login");
} else {
req.session.user = sessionizeUser(user);
res.redirect("/dashboard");
}
});
return loginRouter;
};
export default handler;
authChecker & sessionChecker
// Used for login route
const sessionChecker = (req, res, next) => {
if (req.session.user) {
res.redirect("/dashboard");
} else {
next();
}
};
// If session unavailable, redirect to login
// Used for all protected routes
const authChecker = (req, res, next) => {
if (req.session.user) {
next();
} else {
res.redirect("/login");
}
};
}))
});
dashboard.js
dashboardRouter.get("", authChecker, async (req, res) => {
//code
}
Github repo: GitHub - nimanthadilz/srms
(Use the develop branch for debugging)



