0

Locally this

module.exports.isAuth = (req, res, next) => {
  if (req.isAuthenticated()) {
    next();
    // res.status(200).json({ user: req.user, auth: true });
  } else {
    return res.status(401).json({ auth: false, msg: "Here" });
  }
};

Works perfectly, I get logged in.

But when I try to do it with the backend on Heroku and not locally, I get the "Else" returned to the front end.

The problem is I know where the issue is, most likely, I just feel like I'm in an empty room looking for it.

I get the Json object returned on the front end, even though my passport middleware logs "logged in" on the server. heres the passport middleware

const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const connection = require("./database");
const mongoose = require("mongoose");
const User = mongoose.models.User;
const validPassword = require("../lib/passwordUtils").validPassword;
const cors = require("cors");
passport.use(
  cors({
    origin: [
      "http://2607:fb90:b6e0:a363:f89f:be4b:a976:9ed0:3001",
      "https://frontendfullstack.netlify.app",
      "http://localhost:3001",
      "localhost:3001",
    ],
    credentials: true,
    methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
  })
);

const customFields = {
  usernameField: "username",
  passwordField: "password",
};

passport.use(
  new LocalStrategy(customFields, (username, password, done) => {
    User.findOne({ username: username })
      .then((user) => {
        if (!user) {
          console.log("No user");
          return done(null, false);
        } else {
          const isValid = validPassword(password, user.hash, user.salt);
          if (isValid) {
            console.log("Logged in");

            return done(null, user);
          } else {
            console.log("Wrong Password");
            return done(null, true);
          }
        }
      })
      .catch((err) => {
        done(err);
      });
  })
);

passport.serializeUser((user, done) => {
  done(null, user.id);
});

passport.deserializeUser((id, done) => {
  User.findById(id, (err, user) => {
    done(err, user);
  }).catch((err) => done(err));
});

And just to reiterate, when the server is local, it works, I get logged in and redirected, the site works perfectly.

1 Answers1

1

The problem is that the Passport Local Strategy uses cookies for authentication, and Heroku only allows cookies to be set for its own domain.

As your frontend is hosted in Netlify, if you check the developer tools you will notice no cookie being set. So, the next request you make after logging in, fails.

Not much you can do except hosting the backend together with the frontend in Heroku, that way your app will work.

I answered a similar question a few days ago and left some tips at the end:

Not able to set/receive cookies cross-domain using Netlify and Heroku

EDIT:

Ok, let's see if we can make this work. I haven't worked with React, but the process for building the production app is somewhat similar to Angular from what I read.

  1. First of all, you will want to revert to a prior commit where your app was working. Then create a new branch (i.e. backup) just to be sure if anything goes wrong, you can revert to it. Now, checkout to your main again. This is because Heroku will ignore commits pushed from branches that are not the main one.

  2. Execute npm run build on your React app project folder and you will obtain the compiled files in a build folder. In there you will find the index.html file, and inside the build/static folder you'll find all the .js and .css files with hashed names that contain your app code.

  3. Depending on what location this build folder was generated, you may need to manually copy it so it ends up as a folder inside your Express project folder tree.

  4. Make sure the new folder isn't ignored (check the .gitignore file) so that it will be included in the next commit you'll make.

  5. In the file that sets up your Express server (app.js, server.js or whatever you named it), in the part where the routes are setted, you need to add this line:

app.use(express.static(path.join(__dirname, 'build')));

This line will ensure that when you try to access the / path, Express will send the index.html file to the client. So, it will be just like is hosted in Netlify for example.

Now, you can git add . -> git commit -m 'Deploy test message' -> git push heroku main.

If everything went well, you can now visit the URL that Heroku assigned to your app and you'll see your frontend served in there.

Depending on your folders or environment variables you may run into some other problems, but this should work.

Let me know.

JuanDeLasNieves
  • 354
  • 1
  • 3
  • 8
  • Give me a minute to check all of this out, thank you so much for your response. I had seen that as one of the many causes that it could be. Now, will I run into any issues in the future? why doesnt everyone just host both the front and backend on heroku? Why do people insist on using both? – DrakeColeman Feb 10 '22 at 04:51
  • 1
    I think it has to do with the fact that most developers are using JWTs as means of authentication, and thus not depending on cookies. So, this problem doesn't come up in their apps. I ran into this issue because just like you, I used the Passport Local Strategy. – JuanDeLasNieves Feb 10 '22 at 04:57
  • Oh my gosh, I could really probably use you in the future. I've ran into some simple issues that took me a few days to figure out. Not many people I've met uses it. I'll eventually implement Oauth, but I wanted to start out with the basics first. – DrakeColeman Feb 10 '22 at 04:59
  • I'm by no means an expert, but glad to be helpful. Just happened to run into some of these issues before, and feels good to return something to this community. Keep going forward! – JuanDeLasNieves Feb 10 '22 at 05:08
  • this just turned into a nightmare. my react app is crashing , 503, something about favicon and google isnt helping one bit – DrakeColeman Feb 10 '22 at 07:27
  • Did you change something of your app code? You just need to build the react app and take those files into a static folder and point to it with express.static. Give me an hour or two and I'll write a more detailed guide, I'm at work right now. – JuanDeLasNieves Feb 10 '22 at 14:02
  • I havent changed anything. I keep getting 503 on heroku's front end now, and honestly, i cant find no help on google or stackoverflow. if i do find something similiar it says its my server, which makes no sense since my server and front end work perfectly when my front end is on netlify and/or locally – DrakeColeman Feb 11 '22 at 05:58
  • trying to find an answer for 503 react heroku favicon.ico is impossible so far – DrakeColeman Feb 11 '22 at 05:58
  • nevermind. I got that fixed after a while. but now that i got it working on heroku, im running into the same issue as netlify, where it says im logged in but still returns auth:false – DrakeColeman Feb 11 '22 at 07:26