0

Goodmorning everyone . I am trying to create an authentication system using the MERN stack. Now in my controller I have this login function:

 export const login = async (req, res) => {
  try {
    const { email, password } = req.body;
    const user = await Users.findOne({ email });
    if (!user)
      return res.status(400).json({ msg: "This email does not exist." });

    const isMatch = await bcrypt.compare(password, user.password);
    if (!isMatch)
      return res.status(400).json({ msg: "Password is incorrect." });

    const refresh_token = createRefreshToken({ id: user._id });

    res.cookie("refreshtoken", refresh_token, {
      httpOnly: true,
      path: "/api/user/refresh_token",
      maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
    });

    res.json({ msg: "Login success!" });
  } catch (err) {
    return res.status(500).json({ msg: err.message });
  }
};

This is the function to get the access token instead

export const getAccessToken = (req, res) => {
  try {
    const rf_token = req.cookies.refreshtoken;
    console.log("REQ COOKIE ==> ", req.cookies.refreshtoken);
    if (!rf_token) return res.status(400).json({ msg: "Please login now!1" });

    jwt.verify(rf_token, process.env.REFRESH_TOKEN_SECRET, (err, user) => {
      if (err) return res.status(400).json({ msg: "Please login now!2" });

      const access_token = createAccessToken({ id: user.id });
      res.json({ access_token });
    });
  } catch (err) {
    return res.status(500).json({ msg: err.message });
  }
};

Carrying out tests as a postman, I have no errors. I login with this endpoint

`http://localhost: 5000/api/user/login` 

the cookie is sent correctly after which I call

http://localhost:5000/api/user/refresh_token

and the token is returned to me.

By performing the test from the browser instead, it is not passed and the req.Cookie is always undefined. This is the code in my react app

const dispatch = useDispatch();
  const token = useSelector((state) => state.token);
  const auth = useSelector((state) => state.auth);
  const test = Cookies.get("refreshtoken");

  useEffect(() => {
    const firstLogin = localStorage.getItem("firstlogin");
    console.log(firstLogin);
    // if (firstLogin) console.log(test);

    if (firstLogin) {
      console.log("i'm here");
      const getToken = async () => {
        try {
          const res = await axios.post(
            "http://localhost:5000/api/user/refresh_token",
            null
          );
          console.log(res);
        } catch (error) {
          console.log(error);
        }
      };
      getToken();
    }
  }, [auth.isLogged]);

where am i wrong? Thanks in advance to everyone

Finally this is my server.js

import express from "express";
import mongoose from "mongoose";
import cors from "cors";
import dotenv from "dotenv";
import cookieParser from "cookie-parser";
import postRoutes from "./routes/posts.route.js";
import userRoutes from "./routes/users.route.js";

const app = express();
dotenv.config();

app.use(express.json({ limit: "30mb", extended: true }));
app.use(express.urlencoded({ limit: "30mb", extended: true }));

app.use(cors());
app.use(cookieParser());

app.use("/api/posts", postRoutes);
app.use("/api/user", userRoutes);

app.get("/", (req, res) => {
  res.send("Hello to memories API");
});

const PORT = process.env.PORT || 5000;

mongoose
  .connect(process.env.CONNECTION_URL, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  })
  .then(() =>
    app.listen(PORT, () => console.log(`Server Running on port ${PORT}`))
  )
  .catch((err) => console.log(err.message));
emerald_91
  • 27
  • 1
  • 5

2 Answers2

0

I've run into this a while back. I assume your server and app is not on the same origin. You need to set up CORS appropriately on both ends for it to work; on express and on axios.

This has already been answered here.

Danry
  • 147
  • 15
  • Thanks for the reply . Unfortunately I have already tried, but the problem is not solved at all. I cannot pass the cookie even passing withCredentials: true as in the other question. Always usual error and cookie undefined – emerald_91 Oct 31 '21 at 12:55
  • Hmm. That's weird. Have you passed any options to `cors()` on express yet? Here's mine that worked for reference: `{ origin: "http://localhost:3000", allowedHeaders: [ "Origin", "Content", "Accept", "Content-Type", "Credentials", ], methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"], credentials: true, }` where `origin` is where my app is running. – Danry Oct 31 '21 at 13:31
  • yes , i try everything... it's so frustrating! – emerald_91 Oct 31 '21 at 14:34
  • I just remembered, try setting `sameSite: "none"` when creating the cookie, but that entails that you must also use `secure` attribute and that you must use https connections, unless it's localhost. Hopefully it should work, for more info you may refer here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie. – Danry Oct 31 '21 at 14:48
0

For information I write here the solution that led me to the goal

Backend index.js

app.use(
  cors({
    origin: `${process.env.CLIENT_URL}`,
    credentials: true,
  })
);

endpoint login

res.cookie("refreshtoken", refresh_token, {
      httpOnly: true,
      sameSite: "none",
      secure: true,
      path: "/api/users/refresh_token",
      maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
    });

Frontend

axios.defaults.withCredentials = true;
export const getToken = () => API.post("/users/refresh_token", null);

Thx to @Danry for his help .

emerald_91
  • 27
  • 1
  • 5