fetch: cookies not receiving cookies

21
November 21, 2020, at 11:20 PM

I have a express server running on localhost:5000 and client running on port 3000. After sending post request from client to login using fetch API browser is not setting cookie. I'm getting cookie in response header as 'set-cookie' but it isn't set in the browser at client side.

Here is my fetch request code:

return (
    fetch(baseUrl + "users/login", {
      method: "POST",
      body: JSON.stringify(User),
      headers: {
        "Content-Type": "application/json",
      },
      credentials: "same-origin",
    })

Server side code:

router
  .route("/login")
  .options(cors.corsWithOptions, (req, res) => {
    res.sendStatus(200);
  })
  .post(cors.corsWithOptions, (req, res, next) => {
    passport.authenticate("local", (err, user, info) => {
      if (err) return next(err);
      if (!user) {
        res.statusCode = 401;
        res.setHeader("Content-Type", "application/json");
        res.json({ success: false, status: "Log In unsuccessful", err: info });
      }
      req.logIn(user, (err) => {
        if (err) {
          res.statusCode = 401;
          res.setHeader("Content-Type", "application/json");
          // res.header("Access-Control-Allow-Credentials", true);
          res.json({
            success: false,
            status: "Login Unsuccessful!",
            err: "Could not log in user!",
          });
        }
        var token = authenticate.getToken({ _id: req.user._id });
        res.cookie("jwt-token", token, {
          signed: true,
          path: "/",
          httpOnly: true,
          
        });
        res.statusCode = 200;
        res.setHeader("Content-Type", "application/json");
        res.json({ success: true, status: "Login Successful!", token: token });
      });
    })(req, res, next);
  });
  
Answer 1

How to handle Server-side session using Express-session

Firstly you will need the following packages

npm i express-session connect-mongodb-session or yarn add express-session connect-mongodb-session

Now that we have packages that we need to setup our mongoStore and express-session middleware:

//Code in server.js/index.js (Depending on your server entry point)
import expressSession from "express-session";
import MongoDBStore from "connect-mongodb-session";
import cors from "cors";
const mongoStore = MongoDBStore(expressSession);
const store = new mongoStore({
  collection: "userSessions",
  uri: process.env.mongoURI,
  expires: 1000,
});
app.use(
  expressSession({
    name: "SESS_NAME",
    secret: "SESS_SECRET",
    store: store,
    saveUninitialized: false,
    resave: false,
    cookie: {
      sameSite: false,
      secure: process.env.NODE_ENV === "production",
      maxAge: 1000,
      httpOnly: true,
    },
  })
);

Now the session middleware is ready but now you have to setup cors to accept your ReactApp so to pass down the cookie and have it set in there by server

//Still you index.js/server.js (Server entry point)
app.use(
  cors({
    origin: "http://localhost:3000",
    methods: ["POST", "PUT", "GET", "OPTIONS", "HEAD"],
    credentials: true,
  })
);

Now our middlewares are all setup now lets look at your login route

router.post('/api/login', (req, res)=>{
    //Do all your logic and now below is how you would send down the cooki
    //Note that "user" is the retrieved user when you were validating in logic
    // So now you want to add user info to cookie so to validate in future
    const sessionUser = {
       id: user._id,
       username: user.username,
       email: user.email,
    };
    //Saving the info req session and this will automatically save in your     mongoDB as configured up in sever.js(Server entry point)
    request.session.user = sessionUser;
    //Now we send down the session cookie to client
    response.send(request.session.sessionID);
})

Now our server is ready but now we have to fix how we make request in client so that this flow can work 100%:

Code below: React App/ whatever fron-tend that your using where you handling logging in

//So you will have all your form logic and validation and below
//You will have a function that will send request to server 
const login = () => {
    const data = new FormData();
    data.append("username", username);
    data.append("password", password);
    axios.post("http://localhost:5000/api/user-login", data, {
      withCredentials: true, // Now this is was the missing piece in the client side 
    });
};

Now with all this you have now server sessions cookies as httpOnly

READ ALSO
Github workflow won't connect to my sql server

Github workflow won't connect to my sql server

I've been creating a discord bot through Discordjs on Node

38
AWS KMS got timed out while decrypting

AWS KMS got timed out while decrypting

I'm developing a node app using AWS KMS to encrypt and decrypt dataIt's working just fine, but sometimes an exception happened (1,2 times/day)

36
Creating Amazon Alexa Skill interactive Story(audio files) [closed]

Creating Amazon Alexa Skill interactive Story(audio files) [closed]

Want to improve this question? Update the question so it's on-topic for Stack Overflow

40
UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'voice' of undefined

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'voice' of undefined

So I'm trying to make a command to play music in a vc, but here's my problem whenever I run the command it gives me this error (node:11) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'voice' of undefined whenever I try to do anything...

51