I’m learning full stack with REACT and Express.js and I've been stuck for more than 10 days trying to keep sessions on express that persist from disconnection and refresh. I’m using those modules:
express-session express-mysql-session
The issue Whenever I use my session express middleware and log in:
One cookie will be created in my browser, let's call it 'ABCD'.
Two entries in my DB will be created:
- 'ABCD' with a value
userId:"userId" - 'WXYZ' with a value
userId:"4"(which is the current value of my login Id)
The code
By following the documentation, i've set up my session middleware like this:
const MySQLStoreSession = MySQLStore(session);
const sessionStore = new MySQLStoreSession({
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
clearExpired: true,
checkExpirationInterval: 15 * 60 * 1000,
expiration: 24 * 60 * 60 * 1000,
});
const sessionMiddleware = session({
genid: (req) => {
return uuidv4();
},
secret: 'your secret',
name: 'sessionId',
resave: false,
saveUninitialized: false,
cookie: {
path: '/',
httpOnly: true,
secure: false,
maxAge: 14 * 24 * 60 * 60 * 1000,
},
store: sessionStore,
});
const verifySessionMiddleware = (req, res, next) => {
req.session.userId = 'userId';
if (!req.session || !req.session.userId) {
console.error('Session verification failed:', req.session);
return res.status(401).json("Non authentifié");
}
req.userId = req.session.userId;
next();
};
export { sessionMiddleware, verifySessionMiddleware };
Server file:
app.use(cookieParser());
app.use(sessionMiddleware);
app.use(verifySessionMiddleware);
app.use((req, res, next) => {
console.log('New session:', req.url);
/* console.log('Session data:', req.session); */
next();
})
// utilisation des routes
app.use("/api/auth",authRoutes);
app.use("/api/passwordrecovery",passRecRoutes)
Getting the userId from the login controller:
export const login = async (req, res, next) => {
const { email, password } = req.body;
//verification du regex password
if (!/^(?=.*[A-Za-zÀ-ÿ])(?=.*\d)(?=.*[@$!%*?&])[A-Za-zÀ-ÿ\d@$!%*?&]{8,}$/.test(password)) {
return res.status(400).json('Le mot de passe doit contenir au moins 8 caractères, y compris au moins une lettre et un chiffre.');
}
//verification du regex email
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (!emailRegex.test(email)) {
return res.status(400).json('Veuillez fournir une adresse e-mail valide.');
}
// si l'utilisateur existe
const q = "SELECT * FROM users WHERE email = ?";
const userData = await new Promise((resolve, reject) => {
db.query(q, [DOMPurify.sanitize(email)], (err, data) => {
if (err) return reject(err);
resolve(data);
});
});
if (userData.length === 0) {
return res.status(401).json("Donnée incorrecte!");
}
db.query(q, [DOMPurify.sanitize(req.body.email)], (err, data) => {
if (err) return res.json(err);
if (data.length === 0) {
return res.status(401).json("Donnée incorrecte!");
}
// si le mot de passe est correct
const isPasswordValid = bcryptjs.compareSync(
DOMPurify.sanitize(req.body.password),
data[0].password
);
if (!isPasswordValid)
return res.status(400).json("Email ou mot de passe incorrect");
// Création du token
const token = jwt.sign({ id: data[0].id }, process.env.JWT_SECRET);
//separer le mot de passe de data
const { password, ...other } = data[0];
req.session.userId = data[0].id;
res.cookie("access_token", token, {
httpOnly: true,
secure: 'auto',
sameSite: "none",
maxAge: 14 * 24 * 60 * 60 * 1000,
}).status(200).json(other);
});
};
I have tried to switch cookie parameters to false/true.
I also tried to add promises on my request, because it seems my form send multiple requests.