Search code examples
node.jsexpresspassport.js

passportjs req.user is undefined after login


I am building a server that uses passport.js and jsonwebtokens to authenticate users, this is my passport config code:

passport.use(
    "login",
    new LocalStrategy(
        {
            usernameField: "email",
            passwordField: "password",
            passReqToCallback: true,
        },
        async (req, email, password, done) => {
            try {
                const user = await searchUser({ $or: [{ email }, { username: email }] });

                if (!user) {
                    return done(null, null, ERRORS.INVALID_CREDENTIALS);
                }

                const validate = await user.isValidPassword(password);

                if (!validate) {
                    return done(null, null, ERRORS.INVALID_CREDENTIALS);
                }

                return done(null, user);
            } catch (error) {
                logger(error, "ERROR");
                return done(error);
            }
        }
    )
);
passport.use(
    new JWTStrategy(
        {
            jwtFromRequest: function (req) {
                let token = null;
                if (req && req.cookies) {
                    token = req.cookies["token"];
                }
                return token;
            },
            secretOrKey: process.env.TOKEN_SECRET,
        },
        async function (jwtPayload, cb) {
            try {
                const user = await searchUser({
                    $or: [{ email: jwtPayload.email }, { username: jwtPayload.username }],
                });

                if (!user) {
                    return cb(true);
                }
                console.log(user);
                return cb(null, user);
            } catch (err) {
                return cb(err);
            }
        }
    )
);

passport.serializeUser((user, done) => {
    console.log("Serializing...");
    return done(null, user.id);
});

passport.deserializeUser(async (id, done) => {
    console.log("Deserializing...");
    console.log({ id });
    return done(null, await searchUser({ id }));
});

And this is what my login route does

router.post("/login", (req, res, next) => {
    passport.authenticate("login", function (err, user, info) {
        if (!user) return res.status(401).json(info);

        const token = jwt.sign(
            _.pick(user, [
                "name",
                "surname",
                "email",
                "username",
                "accountType",
                "canComment",
                "id",
            ]),
            process.env.TOKEN_SECRET
        );

        res.cookie("token", token, { expires: new Date(2147483647 * 1000) });

        req.logIn(user, (err) => {
            if (err) return res.status(501).json(ERRORS.UNKNOWN_ERROR);
        });

        res.status(200).json(MESSAGES.LOGIN_SUCCESS);
    })(req, res, next);
});

I have no idea how to fix this since is the first time i am building an express app and actually understanding how passportjs works

Any help is appreciated


Solution

  • I added a middleware that before every route attempts to login the user based on his token in his cookies. This fix seems to work but I don't know if it's the best solution.

    app.use((req, res, next) =>
        passport.authenticate("jwt", function (err, user, info) {
            if (["/login", "/register"].includes(req.path)) return next();
    
            // If the user is something, log it in
            // otherwise the token is missing or invalid, either case remove it
            if (user)
                req.logIn(user, function (err) {
                    if (err) logger("Error in server auth middleware: " + err, "ERROR");
                });
            else res.cookie("token", "", { expires: new Date() });
    
            next();
        })(req, res, next)
    );