Search code examples
reactjsnode.jsexpressjwttoken

There is no token even though I took one in express.js


authUser.js:

const jwt = require("jsonwebtoken");

function authUser(req, res, next) {
  const token = req.cookies.token;

  if (!token) {
    console.log("No token.");
    return res.status(401).json({
      data: null,
      message: "No token.",
      status: 401,
      success: false,
    });
  }

  try {
    const user = jwt.verify(token, process.env.ACCESS_TOKEN);
    req.user = user;
    next();
  } catch (err) {
    console.log("Wrong token or system error.");
    return res.status(401).json({
      data: null,
      message: "Wrong token or system error.",
      status: 401,
      success: false,
    });
  }
}

module.exports = authUser;

index.js:

require("dotenv").config();
const cookieParser = require("cookie-parser");
const express = require("express");
const app = express();
const cors = require("cors");
const mongoose = require("mongoose");
const PORT = 3500;
const connectDB = require("./config/dbConnect");

connectDB();

// app.use(
//   cors({
//     origin: "http://localhost:3500",
//     methods: "GET,POST,PUT,DELETE",
//     credentials: true,
//     optionsSuccessStatus: 200,
//   })
// );

//app.use(cors());

const allowedOrigins = ["http://localhost:5173", "http://localhost:3500"];

// CORS configuration
app.use(
  cors({
    origin: function (origin, callback) {
      // Allow requests with no origin (like mobile apps or curl requests)
      if (!origin || allowedOrigins.includes(origin)) {
        callback(null, true);
      } else {
        callback(new Error("Not allowed by CORS"));
      }
    },
    credentials: true, // Enable credentials (cookies)
    methods: ["GET", "POST", "PUT", "DELETE"],
    allowedHeaders: ["Content-Type"],
  })
);

app.use(cookieParser());
app.use(
  cors({
    origin: ["http://localhost:5173", "http://localhost:3500"],
    credentials: true,
    methods: ["GET", "POST", "PUT", "DELETE"],
    allowedHeaders: ["Content-Type"],
  })
);

app.use(express.urlencoded({ extended: false }));
app.use(express.json());

app.use("/user", require("./routes/userRouter"));
//app.use("/", require("./routes/likedRouter"));

mongoose.connection.once("open", () => {
  console.log("Connected to MongoDB");
  app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
});

userRouter.js:

const express = require("express");
const userRouter = express.Router();
const User = require("../schemas/User");
const authUser = require("../middleware/authUser");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");

userRouter.get("/info", authUser, (req, res) => {
  res.json(req.user);
});

userRouter.get("/isLoggedIn", authUser, (req, res) => {
  res.json({
    data: null,
    message: "User logged in.",
    status: 200,
    success: true,
  });
});

userRouter.post("/register", async (req, res) => {
  try {
    const { username, password } = req.body;
    const hashedPassword = await bcrypt.hash(password, 10);
    const user = new User({ username, password: hashedPassword });
    await user.save();
    res.status(201).send("User saved!");
  } catch (error) {
    console.error(error);
    res.status(500).send("An error happened");
  }
});

userRouter.post("/login", async (req, res) => {
  try {
    const { username, password } = req.body;
    const user = await User.findOne({ username });

    if (!user) {
      return res.status(401).send("User not found");
    }

    const isPasswordValid = await bcrypt.compare(password, user.password);

    if (!isPasswordValid) {
      return res.status(401).json({
        data: null,
        message: "Invalid password.",
        status: 401,
        success: false,
      });
    }

    const token = jwt.sign({ username }, process.env.ACCESS_TOKEN);

    res.cookie("token", token, {
      httpOnly: true,
    });
    res.send("Successful login.");
  } catch (error) {
    console.error(error);
    res.status(500).send("An error happened!");
  }
});

userRouter.get("/logout", (req, res) => {
  res.clearCookie("token");
  res.json({ status: "ok" });
});

module.exports = userRouter;

And App.jsx:

import axios from "axios";
import { useState } from "react";

function App() {
  const [state, setState] = useState(false);
  const [formData, setFormData] = useState({
    username: "",
    password: "",
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData((prevData) => ({
      ...prevData,
      [name]: value,
    }));
  };

  const handleSubmit = async (e) => {
    e.preventDefault();

    try {
      const response = await axios.post(
        "http://localhost:3500/user/login",
        formData
      );
      console.log(response.data); 
      
    } catch (error) {
      console.error("Login error:", error);
      
    }
  };

  const checkLoginStatus = async () => {
    try {
      const response = await fetch("http://localhost:3500/user/isLoggedIn", {
        method: "GET",
        credentials: "include",
      });

      if (response.ok) {
        console.log("Logged in.");
        setState(true);
      } else {
        console.log("Not logged in.");
        setState(false);
      }
    } catch (error) {
      console.error("Error checking login status:", error);
      setState(false);
    }
  };

  return (
    <>
      <div>
        <h2>User login Form</h2>
        <form onSubmit={handleSubmit}>
          <div>
            <label htmlFor="username">Username:</label>
            <input
              type="text"
              id="username"
              name="username"
              value={formData.username}
              onChange={handleChange}
              required
            />
          </div>
          <div>
            <label htmlFor="password">ŞPassword:</label>
            <input
              type="password"
              id="password"
              name="password"
              value={formData.password}
              onChange={handleChange}
              required
            />
          </div>
          <div>
            <button type="submit">Login</button>
          </div>
        </form>
      </div>
      <hr />
      <div>{state ? <p>Yes logged in.</p> : <p>Not logged in.</p>}</div>
      <button onClick={() => checkLoginStatus()}>Check login.</button>
    </>
  );
}

export default App;

The problem is I login with username and password successfully (and in the browser console I see this: Successful login.) but when I clicked the 'Check login.' button it still gives 'Not logged in.' above the button. (And in the browser console this:

   GET http://localhost:3500/user/isLoggedIn 401 (Unauthorized) App.jsx:37
   Not logged in.

and also in the serves side console this:No token.) So this part steps in.

if (!token) {
    console.log("No token.");
    return res.status(401).json({
      data: null,
      message: "No token.",
      status: 401,
      success: false,
    });
  }

What I am missing? Somehow It cannot see the token I have taken.


Solution

  • I think the problem is, that you forgot to add credentials to your login query

    const response = await axios.post(
      'http://localhost:3500/user/login',
      formData,
      { withCredentials: true }
    )