0

I am building a project in react and node, it includes having a persisting session after a login. It works perfectly fine after doing "npm run build" on the react client and moving the "build" folder contents into "public" folder on the server files.

Is there a way to make it work when running client separately? i'm thinking it might have something to do with CORS

On my server side i am using "npm i cors" package as shown below in the code included. Other than that I dont know what to do.

app.js relevant parts

var cors= require('cors');
var session = require('express-session');
app.use(session({
    secret: 'vacations',
    resave: false,
    saveUninitialized: true,
    cookie: { secure: false }
}));
app.use(cors());

login endpoint

router.post("/login", async (req, res) => {
  console.log(req.body);
  let response = {};
  let adjustmentArray = [];

  if(req.body.login == "admin" && req.body.password == "admin"){
    console.log("Detected administrator login")
    Member.findAll({
      where:{
        username: req.body.login,
        password: req.body.password
      }
    })
    .then(admin =>{
      req.session.isLogged = 1;
      req.session.firstname = admin[0].dataValues.firstname;
      req.session.userid = admin[0].dataValues.id;
      req.session.isAdmin = 1;

      response.userid = admin[0].dataValues.id;
      response.firstname = admin[0].dataValues.firstname;
      response.isAdmin = 1;

      adjustmentArray.push(response);

      res.json(adjustmentArray);
    })
    .catch(err=>{
      console.log(err);
      console.log("err");
      res.json([]);
    })




  }

clientside code

  async sendLogin() {
    let loginObj = {
      login: this.props.usernamelogin,
      password: this.props.passwordlogin
    };

    let response = await fetch("http://localhost:3000/members/login", {
      method: "POST",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json"
      },
      body: JSON.stringify(loginObj)
    });

    let user = await response.json();

    console.log(user);

    if (user.length !== 0) {

      if(user[0].isAdmin){

        this.props.dispatchAdminLogin(user[0]);
        alert("Hey boss")
        this.setState({ loginmsg: "" });
        this.props.history.push("/admin")
      }
      else{
        this.props.dispatchLogin(user[0]);
        alert("Logged in! Redirecting...");
        this.setState({ loginmsg: "" });
        this.props.history.push("/");
      }
    } else {
      this.setState({
        loginmsg: "Please check username/password and try again"
      });
    }
  }

  async componentDidMount() {
    let response = await fetch("http://localhost:3000/checksession");
    let user = await response.json();

    console.log(user);
    if (user.isLogged) {
      this.props.dispatchLogin(user);
    }
  }

router.get("/checksession", async (req, res) => {

  if (req.session.isLogged) {


    Member.findAll({
      where: {
        id: req.session.userid,
        username: req.session.firstname
      }
    })
      .then(member => {

        if (member.length != 0) {


            let response = {};


            response.isLogged = 1;
            response.firstname = member[0].dataValues.firstname
            response.userid = member[0].dataValues.id


            res.json(response)
        } 

        else {
          //i think this code will never happen
            console.log("didnt find member, killed session")
          req.session.destroy();

          res.json({isLogged:0});
        }
      })
      .catch(err => {
        //also pretty likely this never happens
        console.log(err);
        console.log("couldnt find member?");
        res.json({isLogged:0});
      });
  }
  else{
      console.log("i didnt pass session check")
      res.json({isLogged:0})
  }

});

I want session to persist when running client and server on separate ports in seperate instances of visual studio.

adame21
  • 133
  • 1
  • 13
  • Where is your code failing? Is it making a connection to the server? Is there an error message? What have you tried to fix it? There is not much to go off of and not much evidence you have made an attempt. – Trobol Apr 08 '19 at 18:46
  • session does not persist on refresh when its run on its own from the client side visual studio instance, only when moved into server files. im sorry if im not making sense please ask me something specific. when i say doesent persist i mean its former keys are undefined – adame21 Apr 08 '19 at 19:35
  • Does the client connect to the server when run on its own? (Not does the server remember it, add a console log to say when it connects) Also if you could share client side code it would be helpful. – Trobol Apr 08 '19 at 19:39
  • oh sorry ill get right to it adding client side. the client makes http requests with fetch to the server, the client is running on localhost:3001 and the server is on localhost:3000 – adame21 Apr 08 '19 at 20:01
  • So, I'm not sure but I think that on `router.get("/checksession", async (req, res) => {` you are getting the response from the client which has not idea of the login. You then check it in `if (req.session.isLogged) {` but (to repeat myself) the `req` object is from the client. Why can't you build react into your public folder? – Trobol Apr 08 '19 at 21:15
  • might be silly but thats how it was required to be done - regarding the why i cant put it in public. i know what you mean but checksession only happens after the login was done which triggers req.session.isLogged=1, Ive been reading and think it might be a withcredentials issue so im looking into that, but i was told somewhere else i can just use a proxy to make it same domain, im still not sure what to do to make this work. – adame21 Apr 09 '19 at 16:22
  • You said that it allows you to login, but doesn't remember you. When you make the request to /checksession that will make the request to the client backend (on port 3001), which has no idea of the login. You can a) serve client and server code from the same server (aka move into public folder) or b) inside your check session function make a request to the server on port 3001 and check that response for credentials – Trobol Apr 09 '19 at 16:30
  • but port 3001 is where the client is running, how can it respond? the component did mount function is on a separate home component that when you get redirected to (after login) does the checksession, and the session.isLogged should be 1 because it was previously set on the login post request but its undefined – adame21 Apr 09 '19 at 16:39
  • What you refer to as the "client" is also a server. It is a server that is only for sending the files that have been requested. What you call the "server" is very similar to the "client" server but it has some extra code that you wrote that will create a session when you send the login credentials. When you are redirected, your browser makes a request to "/checksession". This will send a request to the "client" server which will respond with something, I'm not sure what, but it WILL NOT have a session because the session was created on the "server" server. – Trobol Apr 09 '19 at 16:49
  • This might help to combine your "client" and "server": https://medium.com/@maison.moa/setting-up-an-express-backend-server-for-create-react-app-bc7620b20a61 – Trobol Apr 09 '19 at 16:52
  • I tried adding the "proxy": "localhost:3000" configuration to react but it did nothing. I guess im probably not explaining myself correctly or not understanding it all well enough yet. thanks for the help – adame21 Apr 09 '19 at 17:11
  • If you add `app.use(express.static('path/to/Client/build'))` to your express server (and change the path). It should allow you to serve the react files from the server without putting them in the `public` folder. You also may already have a line that has `app.use(express.static(...))`. If so, are there files in public you need to access? If not, remove that line and replace it with the one above. – Trobol Apr 09 '19 at 17:23
  • Oh i see what that would do, but that would point the server to my build folder on the react app, but i would still need to do npm run build right? what im trying to do is make it work when still running on just npm start before compiling build folder – adame21 Apr 09 '19 at 17:44
  • You could make a new npm command that would start your server and build your app. Or you could use something like [this](https://stackoverflow.com/a/42773333/8781351). – Trobol Apr 09 '19 at 17:47
  • wow that looks perfect, that would refresh the build folder on any change? – adame21 Apr 09 '19 at 17:51
  • According to the answer, yes. – Trobol Apr 09 '19 at 17:54

0 Answers0