Palx
Palx

Reputation: 57

Error while generating token and passing it between frontend and backend in MERN stack using jsonwebtoken

ERROR:

TypeError: Cannot read property 'jwtoken' of undefined

Overview: A token is generated using JSONwebtoken whenever a user logs into his account. This token is then passed to the backend. The user can see the 'about page' only after the token stored in cookies is verified against the token stored in the database (token is generated and stored in the database when the user logs in).

CODE (backend files):

authenticate.js (middleware)

const authenticate = async (req, res, next) => {
  try {
    const token = req.cookies.jwtoken;  //this line throws an error
...//more code

auth.js: (router file)

router.post("/signin", async (req, res) => {
  let token;
  const { email, password } = req.body;

  if (!email || !password) {
    return res.status(422).json({ error: "invalid creds" });
  }

  try {
    const userLogin = await User.findOne({ email: email });

    if (!userLogin) {
      return res.status(422).json({ error: "invalid email" });
    } else {
      token = await userLogin.generateAuthToken();

      res.cookie("jwtoken", token, {
        expires: new Date(Date.now() + 2592000000),
        httpOnly: true,
      });

      const isMatch = await bcrypt.compare(password, userLogin.password);
      if (!isMatch) {
        return res.status(422).json({ error: "invalid password" });
      }
      res.status(201).json({ msg: "login successful" });
    }
  } catch (error) {
    console.log(error);
  }
});

router.get("/about", authenticate, (req, res) => { //authenticate is middleware
  res.send(req.rootUser);
});

userSchema.js-> token is generated , database model schema

  try {
    let tokenVal = jwt.sign({ _id: this._id }, process.env.SECRET_KEY);
    this.tokens = this.tokens.concat({ token: tokenVal });
    await this.save();
    return tokenVal;
  } catch (err) {
    console.log(err);
  }
};

frontend files:

about.js

const About = () => {
  const history = useHistory();

  const callAboutPage = async () => {
    try {
      const res = await fetch("/about", {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json", 
        },
        credentials: "include", //i.e send cookies
      });

      const data = await res.json();
      console.log(data);

      if (!res.status === 200) {
        const error = new Error(res.error);
        console.log(error);
        throw error;
      }
    } catch (err) {
      console.log(err);
      history.push("/login");
    }
  };

  useEffect(() => {
    callAboutPage();
  });

login.js

onst Login = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const history = useHistory();

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

    const res = await fetch("/signin", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },

      body: JSON.stringify({
        email,
        password,
      }),
    });
    const data = res.json();
    if (!data || res.status === 422) {
      window.alert("Invalid creds");
    } else {
      window.alert("LOGIN successful");
      history.push("/");
    }
  };
TypeError: Cannot read property 'jwtoken' of undefined
    at authenticate (F:\projects\mern\basicMernProject\server\middleware\authenticate.js:6:31)
    at Layer.handle [as handle_request] (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\layer.js:95:5)
    at next (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\route.js:137:13)        
    at Route.dispatch (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\layer.js:95:5)
    at F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:281:22
    at Function.process_params (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:335:12)
    at next (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:275:10)        
    at Function.handle (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:174:3)
    at router (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:47:12)       
    at Layer.handle [as handle_request] (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:317:13) 
    at F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:335:12)
    at next (F:\projects\mern\basicMernProject\server\node_modules\express\lib\router\index.js:275:10)        
    at jsonParser (F:\projects\mern\basicMernProject\server\node_modules\body-parser\lib\types\json.js:110:7) 

Upvotes: 0

Views: 579

Answers (1)

aleksxor
aleksxor

Reputation: 8370

Looks like you don't use any cookie related middlewares. Express doesn't parse request cookie headers by default. That's why your req object doesn't have cookies property. To make it work you should consider adding a cookie-parser middleware when initializing your express application:

// server.js?
const express = require('express')
const cookieParser = require('cookie-parser')

const server = express()
server.use(cookieParser())

This middleware creates and populates cookies property on the req object.

Upvotes: 1

Related Questions