Search code examples
reactjsexpresspassport.js

how to change port in express redirect to React port?


Im using Express application for my backend on port 9000 and a react app for frontend on port 3000.

also, I'm using Passport JS for authentication. there's a option in passport.authenticate which redirect users if they authenticate successfully or not.

my problem is Express app redirect to /dashboard:9000 not /dashboard:3000 (my frontend).

how can i change redirect port in express?

my express login logic:

router.post("/login", passport.authenticate('local',
    { failureRedirect: '/login',
      failureFlash: true }), function(req, res) {
        if (req.body.remember) {
          req.session.cookie.maxAge = 30 * 24 * 60 * 60 * 1000; // Cookie expires after 30 days
        } else {
          req.session.cookie.expires = false; // Cookie expires at end of session
        }
      res.redirect('/dashboard'); //redirect to dashboard
});

react submit form logic:

const submitForm = async (event) => {
    axios
      .post(
        "http://localhost:9000/login",
        {
          "username":email,
          "password":password,
          "remember":shouldRemember
      }
      )
      .then((res) => {
        //Should I redirect using react router?
      })
      .catch((err) => {
        console.log(err)
        if(err.response.status == 401){
          setFormError(true)
        }
      });
  };

Browser network debugger

I tried to hardcode the port in express app redirects , but it didnt work.

im also using cors.


Solution

  • You appear to have confused between server side rendering and client side rendering.

    res.redirect('/dashboard') is used to serve for Server-Side Rendering(SSR).

    You cannot redirect the user from a server in Client-Side Rendering(CSR). (Like in React.js).

    In your case, you need to set and sent the response - status and error to the client and you need to handle the error statuses in the client side code only.

    router.post("/login", passport.authenticate('local',
        { failureRedirect: '/login-failure',
          failureFlash: true }), function(req, res) {
            if (req.body.remember) {
              req.session.cookie.maxAge = 30 * 24 * 60 * 60 * 1000; // Cookie expires after 30 days
            } else {
              req.session.cookie.expires = false; // Cookie expires at end of session
            }
          res.status(200).send({message: "Success", user: userDetails}); // Set status as OK(200) and send the required user details to the client side
    });
    

    In your code you have used in-built local authentication Strategy. You can override and can implement your own logic for this. So based on your code, you need to set a route for '/login-failure' to send the status and error-message to the client side.

    router.get("/login-failure", function(req, res) {
      res.status(401).send({ message: "Authentication failed" });
    });
    

    Then in the client side you need to handle the error responses using axios interceptors. Refer axiosDocs.

    // Add a response interceptor
    axios.interceptors.response.use(function (response) {
        return response;
      }, function (err) {
         if (
           err.response.status === 401 ||
           err.response.status === 403 ||
           err.response.data.err
         ) {
             sessionStorage.clear();
             window.location.reload();
      }
        return Promise.reject(err);
      });
    

    You can handle for any error codes other than 2xx codes