0

I'm developing my final project and I'm trying to build a MERN project. I'm trying to implement an authentication with passport, and it works in development, but when I deployed I keep getting this error

Access to fetch at 'https://hospitalveterinariopeninsular.herokuapp.com/api/auth/googleLogin/success' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

But if I manually access the site: https://hospitalveterinariopeninsular.herokuapp.com/api/auth/googleLogin/success', I get the response I need. So I don't know if it's a problem of the server or from React.

This is my code in the server:

Index.js

const app = express();
app.use(
  cookieSession({ name: "session", keys: ["whatever"], maxAge: 24 * 60 * 60 * 100 })
);

app.use(passport.initialize());
app.use(passport.session());

dbConnection();

// CORS
app.use(
  cors({
    origin: process.env.CLIENT_URL,
    methods: "GET,POST,PUT,DELETE, PATCH",
    credentials: true,
    maxAge: 3600,
  })
);
app.use(express.static(path.join(__dirname, "/public")));

app.use(express.json());

app.use("/api/auth", authRoutes);

AuthRoutes.js

router.get(
  "/google",
  passport.authenticate("google", { scope: ["profile", "email"] })
);

// callback from google
router.get(
  "/google/callback",
  passport.authenticate("google", {
    failureRedirect: "/api/auth/googleLogin/failed",
    successRedirect: `${process.env.CLIENT_URL}/#/auth`,
  })
  // googleAuth
);

router.get("/googleLogin/success", (req, res) => {
  console.log("success", req.user);
  if (req.user) {
    res.status(200).json({
      success: true,

      message: "successfull",
      user: req.user,
      token: req.user.token,
      //   cookies: req.cookies
    });
  }
});

Code from React

export const AuthPage = () => {
  useEffect(() => {
    const getUser = () => {
      fetch(`${process.env.REACT_APP_API_URL}/auth/googleLogin/success`, {
        method: "GET",
        credentials: "include",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
          "Access-Control-Allow-Credentials": true,
        },
      })
        .then((response) => {
          console.log("THIS IS THE RESPONSE", response);
          if (response.status === 200) return response.json();
          throw new Error("authentication has been failed!");
        })
        .then((resObject) => {
          console.log("POR FAVOR********", resObject);
          localStorage.setItem("token", resObject.token);
          localStorage.setItem("token-init-date", new Date().getTime());
          dispatch(startChecking());
        })
        .catch((err) => {
          console.log(err);
        });
    };
    getUser();
  }, []);


  return (...);
};

Edit to add github links Backend: https://github.com/JavierGarciaGomez/hvp2021backend Frontend: https://github.com/JavierGarciaGomez/hvp2021frontend

enviromental variables:

React:
REACT_APP_API_URL=https://hospitalveterinariopeninsular.herokuapp.com/api
Node: 
PORT=4000
CLIENT_URL=http://localhost:3000
CLIENT_URL_PROD=https://www.hospitalveterinariopeninsular.com
  • Does this answer your question? [Why does my JavaScript code receive a "No 'Access-Control-Allow-Origin' header is present on the requested resource" error, while Postman does not?](https://stackoverflow.com/questions/20035101/why-does-my-javascript-code-receive-a-no-access-control-allow-origin-header-i) – Heretic Monkey Feb 08 '22 at 14:04
  • Have you set/updated the `process.env.CLIENT_URL` environment variable so that it reflects the right origin ? – Bao Huynh Lam Feb 08 '22 at 14:06
  • What is the value of process.env.CLIENT_URL in local and heroku? – JRichardsz Feb 08 '22 at 14:09
  • Yes, is correctly set in heroku as an enviromental variable as: https://www.hospitalveterinariopeninsular.com Actually when the router.get( "/google/callback", (...)) is called, it redirects me correctly to https://www.hospitalveterinariopeninsular.com/#/auth – Javier García Feb 08 '22 at 14:17
  • cors error is when a background consumption is made. Redirects don't throw that error. Just to try, use * in cors `cors({origin: "*"` – JRichardsz Feb 08 '22 at 14:25
  • I have tried that, but when i do that it throws me an error that says something similar, but specifies that i cant use a wild card. Im gonna retry and paste the error – Javier García Feb 08 '22 at 14:27
  • This is the error that i get when i use * as origin: Access to fetch at 'https://hospitalveterinariopeninsular.herokuapp.com/api/auth/googleLogin/success' from origin 'https://www.hospitalveterinariopeninsular.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include' – Javier García Feb 08 '22 at 14:30
  • @Javier The CLIENT_URL is the URL of your frontend. Since (I suppose) your frontend is still on localhost, you must set CLIENT_URL "http://localhost:3000", not the URL of your backend. The purpose is to let your backend know the URL of your frontend so CORS can allow your frontend – Bao Huynh Lam Feb 08 '22 at 14:38
  • @BaoHuynhLam, i have tried to do that with my client frontend in localhost, and also deployed in the site: https://www.hospitalveterinariopeninsular.com. Changing the enviromental variable in Heroku. It wont work in anyway. It works perfect when i run both the server and client in localhost. You can try the auth if u want in "Acceso" of the deployed site. The other request that i made, works fine – Javier García Feb 08 '22 at 14:50
  • Seems like wildcard is not an option, `localhost` did not work and `hospitalveterinariopeninsular.com` also does not work for CLIENT_URL. Just a random thought - have you tried `www.hospitalveterinariopeninsular.com` ? Remember to access the backend from where you set the CLIENT_URL variable – Bao Huynh Lam Feb 08 '22 at 15:06
  • 1
    @BaoHuynhLam just tried and instead of redirecting to the site, goes here: /api/auth/google/www.hospitalveterinariopeninsular.com/ Is very odd, im trying to understand why – Javier García Feb 08 '22 at 15:23
  • cors is easy to configure: https://github.com/jrichardsz/nodejs-express-snippets/blob/master/cors/index.js The are some line in your backend that is spoiling everything. If you want help, replicate the issue on a minimal sample on github and share us the url – JRichardsz Feb 08 '22 at 15:27
  • @JRichardsz, i gonna read that link, and i have editted the question to add the github links. Thanks in advance – Javier García Feb 08 '22 at 15:38

1 Answers1

0

The order is highly sensitive on express middlewares.

In your entrypoint you have this:

app.use(passport.initialize());
app.use(passport.session());

...

// CORS
app.use(
  cors({
    origin: process.env.CLIENT_URL,
    methods: "GET,POST,PUT,DELETE, PATCH",
    credentials: true,
    maxAge: 3600,
  })
);

Put the cors initialization before passport initialization:

// CORS
app.use(
  cors({
    origin: process.env.CLIENT_URL,
    methods: "GET,POST,PUT,DELETE, PATCH",
    credentials: true,
    maxAge: 3600,
  })
);

....

app.use(passport.initialize());
app.use(passport.session());

I think your passport routes are not being detected by your cors configuration because those where configured before the cors magic

JRichardsz
  • 14,356
  • 6
  • 59
  • 94