I try to do a login via a LocalStrategy in Passport, but the serializeUser and deserializeUser functions don't seem to be called at all. The versions of the ‘Relevant’ packages are:
"express": "^4.21.2",
"express-mysql-session": "^3.0.3",
"express-session": "^1.18.1",
"passport": "^0.7.0",
"passport-local": "^1.0.0",
passport.js file: Console Outputs are only ‘login’, never ‘serialize’ or ‘deserialize’.
const passport = require("passport"),
LocalStrategy = require("passport-local").Strategy;
passport.use("local.login", new LocalStrategy({
usernameField: 'address',
passwordField: 'token',
passReqToCallback: true
}, async (req, _username, _password, done) => {
const body = JSON.parse(req.body.body);
const user = {
id: `${Date.now()}`,
token: "123"
};
console.log("login");
return done(null, user);
}));
passport.serializeUser((user, done) => {
console.log("serialize");
return done(null, user.id);
});
passport.deserializeUser((id, done) => {
console.log("deserialize");
return done(null, {
id: id,
token: "123"
});
The rest of the code in this respect
index.js
const express = require("express"),
passport = require("passport"),
session = require("express-session"),
MySQLStore = require("express-mysql-session")(session),
{ database } = require("./lib/config/keys"),
bodyParser = require("body-parser"),
{ body } = require("express-validator");
...
app.set("port", process.env.PORT || 80);
...
// Middlewares
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(session({
secret: "secret",
resave: false,
saveUninitialized: true,
store: new MySQLStore(database)
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(body());
require("./passport");
app.use((req, res, next) => {
app.locals.user = req.user;
next();
});
...
auth.js
// Requirements
const express = require("express"),
router = express.Router(),
passport = require("passport");
router.post("/login", async (req, res, next) => {
. . .
passport.authenticate("local.login", (err, user, info, status) => {
if (err) {
console.error(err);
return res.send(false);
}
res.send(true);
})(req, res, next);
}
);
. . .
The problem was that req.login(user, callback)
was missing inside the authentication callback. Passport doesn’t automatically serialize the user unless req.login()
(or req.logIn()
) is called. This means that the serializeUser and deserializeUser functions were never triggered.
Solution:
Modify the /login
route in auth.js
to include req.login()
after successful authentication:
router.post("/login", async (req, res, next) => {
passport.authenticate("local.login", (err, user, info) => {
if (err) {
console.error(err);
return res.send(false);
}
if (!user) {
return res.send(false);
}
// Here.
req.login(user, (loginErr) => {
if (loginErr) {
console.error(loginErr);
return res.send(false);
}
res.send(true);
});
})(req, res, next);
});
Why this works:
passport.authenticate()
only verifies the user but does not automatically establish a session.req.login(user, callback)
tells Passport to serialize the user, triggering serializeUser and deserializeUser.After adding req.login(user, callback)
, everything works as expected! Now, serializeUser
and deserializeUser
are being called properly. Hopefully, this helps anyone else facing the same issue.