I am new to Node and Express, and this is the first time I ask a question on stack overflow. Please forgive me if I made any beginner mistakes.
I was trying to build a book-sharing web app for users to upload and share books online. The tech stack I use is Node, Express, MongoDB and React. I have used Passport.js to handle user authentication and session. The session created after the user has logged in doesn't seem to persist upon redirection or page refresh.
Below is the route that handles user log in and sign up:
user.route.js
const mongoose = require("mongoose");
const express = require("express");
const router = express.Router();
const passport = require("passport");
const User = require("../models/User");
router.route("/register").post((req, res, next) => {
const newUser = new User({
username: req.body.username,
email: req.body.email
});
// Register new User with password
// Password will be automatically hashed and salted
User.register(newUser, req.body.password, (error, user) => {
if (error) {
next(error);
} else {
passport.authenticate("local")(req, res, () => {
res.status(200).json(req.isAuthenticated());
})
}
})
});
router.route("/login").post((req, res, next) => {
const loggedInUser = new User({
username: req.body.username,
password: req.body.password
});
req.login(loggedInUser, error => {
if (error) {
next(error);
} else {
console.log(req.user);
console.log(req.session.id);
passport.authenticate("local")(req, res, () => {
res.status(200).json(req.isAuthenticated()); // Send login status to Login component
});
}
});
});
module.exports = router;
Both console.log(req.user) and console.log(req.session.id) show that the session was indeed created.
However, the problem came when I was trying to access req.user in the book route. I wanted to allow users to upload and save books into their own account. req.user no longer exists and console.log shows "undefined". Below is a section of book.route.js that handles post request by users:
router.route("/add-book").post(upload.single("image"), (req, res, next) => {
if (req.file) {
const newBook = new Book({
name: req.body.name,
author: req.body.author,
description: req.body.description,
genre: req.body.genre,
image: {
data: fs.readFileSync(req.file.path), // Get buffer data
contentType: req.file.mimetype
}
});
console.log(req.user);
User.findOne({_id: req.user._id}).
populate("books").
exec((error, newBook) => {
if (error) {
return next(error);
} else {
console.log("Saved to user!");
}
});
// Ignore below
// newBook.save((error, savedBook) => {
// if (error) {
// return next(error);
// } else {
// console.log(savedBook);
// res.status(201).json(savedBook); // New book created
// }
// });
} else {
console.log("No file uploaded");
}
});
Below is my server.js file:
require("dotenv").config()
const express = require("express");
const cookieParser = require('cookie-parser')
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const cors = require("cors");
const dbConfig = require("./database/db"); // db connection
const session = require("express-session");
const passport = require("passport");
const User = require("./models/User");
// Express route
const bookRoute = require("./routes/book.route");
const userRoute = require("./routes/user.route");
const app = express();
app.use(cookieParser())
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(cors());
// Connect to MongoDB database;
mongoose.connect(dbConfig.db, {useNewUrlParser: true, useFindAndModify: false, useUnifiedTopology: true}).then(() => {
console.log("Database successfully connected!");
}).catch((error) => {
console.log(`Database not connected: ${error}`);
});
mongoose.set("useCreateIndex", true);
// Configure and setup session
app.use(session({
secret: process.env.SECRET,
resave: false,
saveUninitialized: false,
}));
// initialize passport and use it with session
app.use(passport.initialize());
app.use(passport.session());
// passport config
// For more information on serialize and deserialize: https://stackoverflow.com/questions/27637609/understanding-passport-serialize-deserialize
passport.use(User.createStrategy());
// used to serialize the user for the session
passport.serializeUser((user, done) => {
done(null, user.id); // Save user id into session
});
// used to deserialize the user
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
app.use("/", userRoute);
app.use("/", bookRoute);
// Port
//process.env is a global variable injected by Node at runtime
// It represents the state of the system environment of your application
const port = process.env.PORT || 4000;
app.listen(port, () => {
console.log(`Server is listening at port ${port}`);
});
// 404
app.use((req, res, next) => {
console.log(req.user);
res.status(404).send("Sorry page not found!");
})
May I know what is the problem? I truly appreciate any help provided. Thank you.