Home > Software design >  Express creates new sessions whenever frontend makes a new POST or GET request using Axios
Express creates new sessions whenever frontend makes a new POST or GET request using Axios

Time:11-11

I have an express server backend where I am using sessions to keep track of user when they are logged in or not, and using passportJS for authentication. ReactJS for the frontend. React runs on default port 3000 and express app runs on 5500.

Right now, whenever I use a post request to /api/login it logs in the user and sends 200 ok and creates a session with passport user object and then redirects to profile page, I have another GET request that requests to get the user data. The profile page sends a GET request to /api/profile which checks if the user is authenticated and if yes sends back user data to populate profile page with user details. But right now, every time the profile page sends a GET request back to the server it creates a new session overwriting the sessions created in /api/login and loses user data showing the user is not Authenticated.

Here is my server.js file

const express = require("express");
const MongoStore = require("connect-mongo");
const indexRouter = require("./routes/index");
const app = express();
const cors = require("cors");
const bodyparser = require("body-parser");
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const passport = require("./Authentication/passportConfig");
const session = require("express-session");
const cookieParser = require("cookie-parser");
dotenv.config({ path: "../app/Private/.env" });
let port = process.env.PORT;

app.use(bodyparser.json());
app.use(bodyparser.urlencoded({ extended: true }));
app.use(
  cors({
    origin: "http://localhost:3000",
    methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
    credentials: true,
  })
);

app.use(cookieParser("secret"));
app.use(
  session({
    secret: "secret",
    store: MongoStore.create({ mongoUrl: process.env.ADMIN_URI }),
    resave: false,
    saveUninitialized: false,
    cookie: { maxAge: 30 * 24 * 60 * 60 * 1000, httpOnly: true },
  })
);
app.use(passport.initialize());
app.use(passport.session());

//Database connection process
mongoose
  .connect(process.env.ADMIN_URI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  })
  .then(() => console.log("connected to database"))
  .catch(console.error);

//Route creation
app.use("/api", indexRouter);

app.listen(port, () => console.log("Server connected and running: "   port));

and here are the two routes in my indexRouter

const express = require("express");
const router = express.Router();
const passport = require("../Authentication/passportConfig");
const dotenv = require("dotenv");
dotenv.config({ path: "../app/Private/.env" });
const nodemailer = require("nodemailer");
const User = require("../model/user");
const hash = require("../Authentication/passwordHash");
const validator = require("node-email-validation");
const Appointment = require("../model/appointment");

router.post("/login", passport.authenticate("local"), (req, res) => {
  var time = new Date(Date.now());
  console.log(
    "Session ID before @ /login route: "  
      time.toLocaleTimeString()  
      ": "  
      req.sessionID
  );
  if (req.user) {
    console.log("Session ID after @ /login route: "   req.sessionID);
    console.log("User is logged in: "   req.user.username);
    console.log("User is Authenticated: "   req.isAuthenticated());
    res.status(200).json({ message: "Login successful" });
  } else {
    res.send(400).json({ message: "User not found" });
  }
});

router.get("/profile", function (req, res) {
  var time = new Date(Date.now());
  console.log(
    "Session ID @ /profile route: "  
      time.toLocaleTimeString()  
      ": "  
      req.sessionID
  );
  if (req.isAuthenticated()) {
    console.log(req.isAuthenticated());
    console.log("user: "   req.user.username);
    return res.status(200).json(req.user);
    num = num   1;
  } else {
    console.log("else Statement");
    return res.status(302).json({ message: "User not found" });
  }
});

Here is the output from console logging session at the different routes

Session ID before @ /login route: 5:41:07 PM: 8Z1RebDKynOESWoQ5ecA3EecOojmthL9
Session ID after @ /login route: 8Z1RebDKynOESWoQ5ecA3EecOojmthL9
User is logged in: [email protected]
User is Authenticated: true
Session ID @ /profile route: 5:41:09 PM: -peiT761fG_ZY9gLgWFpqeUE6hTZmRQV
else Statement
Session ID @ /profile route: 5:41:09 PM: kgXFngZMamCqh4mapynMQQN7cgL9Er-1
else Statement
Session ID @ /profile route: 5:41:09 PM: zCZTtlsK-g0MSvo9j5ZbAAs35vaXtsnO
else Statement
Session ID @ /profile route: 5:41:09 PM: Oq8J-s08m66P5JuuTO1RI5ZIy8oOeXRD
else Statement

Here is the ReactJS frontend calls in Login page

const config = {
    headers: {
      "Access-Control-Allow-Origin": "http://localhost:3000",
      "Access-Control-Allow-Methods": "GET,PUT,POST,DELETE,PATCH,OPTIONS",
      "Access-Control-Allow-Credentials": "true",
    },
  };

const isLoggedIn = () => {
    axios
      .get("http://localhost:5500/api/profile", config)
      .then((res) => {
        console.log("Is user logged in status: "   res.status);
        console.log(res.data);
        if (res.status === 200) {
          window.location.href = "/MyProfile";
        }
      })
      .catch((err) => {
        console.log("err"   err);
      });
  };

  /*
    on Submit function for the login page
    */
  const onSubmitLogIn = (e) => {
    e.preventDefault();
    const user = {
      username: username.toString().toLowerCase(),
      password: password,
    };
    axios
      .post("http://localhost:5500/api/login", user, config)
      .then((res) => {
        console.log(res.data);
        if (res.status === 200) {
          setSuccessMessage(true);
          setTimeout(() => {
            window.location.href = "/MyProfile";
          }, 2000);
        }
      })
      .catch((err) => {
        setErrormessage(true);
      });
  };

Here is the hook call and get request in profile.jsx

useEffect(() => {
    fetchUserData();
  }, []);

  const fetchUserData = () => {
    axios
      .get("http://localhost:5500/api/profile", config)
      .then((res) => {
        console.log("res: "   res);
        console.log("User: "   res.data);
        setUserData(res.data);
      })
      .catch((err) => {
        console.log(err);
        console.log(err.response);
      });
  };

I don't understand where I am going wrong and why the call in profile creates a new session.

CodePudding user response:

Add the {withCredentials: true} option to your Axios call so that Axios will send cookies (and thus the sessions cookie) with your request.

 const fetchUserData = () => {
    axios
      .get("http://localhost:5500/api/profile", {withCredentials: true})
      .then((res) => {
        console.log("res: "   res);
        console.log("User: "   res.data);
        setUserData(res.data);
      })
      .catch((err) => {
        console.log(err);
        console.log(err.response);
      });
  };

When cookies are not sent with the request, then your session cookie is not present and the backend creates a new session everytime.

  • Related