Home > Net >  How to fix JsonWebTokenError in node.js using express and reactjs?
How to fix JsonWebTokenError in node.js using express and reactjs?

Time:03-14

I am trying to show the page only if the Jsonwebtoken is verified and the user is logged on to the website, else show him the sign-in page.

However, I can see the token is generated in MongoDB, and also when I console log I can see that it is all good. But the issue is when I try to verify it using an already generated jwt token i.e.

req.cookies.signinToken

it shows an error.

Please the detail code below:

On app.js

const dotenv = require("dotenv");
const mongoose = require("mongoose");
const express = require("express");
const app = express();

const jwt = require("jsonwebtoken");
const cookieParser = require("cookie-parser");

dotenv.config({ path: "./config.env" });
require("./db/connection");

app.use(express.json());
app.use(cookieParser());

app.use(require("./router/route"));

const PORT = process.env.PORT;

app.listen(5000, () => {
    console.log(`server running on ${PORT}`);
});

On route.js

const express = require("express");
const bcrypt = require("bcrypt");
const router = express.Router();
const jwt = require("jsonwebtoken");

require("../db/connection");
const User = require("../model/newUserSchema");
const auth = require("../middleware/auth");

// router.get("/", (req, res) => {
//     res.send("hello am backend sever");
// });

//Signup or  Register Part
router.post("/signup", async (req, res) => {
    const { username, email, cpassword, retypePassword } = req.body;

    if (!username || !email || !cpassword || !retypePassword) {
        return res.status(422).json({ error: "please enter valid details" });
    }

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

        if (UserExist) {
            return res.status(422).json({ error: "email already exist" });
        } else if (cpassword !== retypePassword) {
            return res.status(422).json({ error: "password incorrect" });
        } else {
            const user = new User({
                username,
                email,
                cpassword,
                retypePassword,
            });

            const userResgister = await user.save();

            if (userResgister) {
                return res.status(201).json({ message: "signup successfully" });
            }
        }
    } catch (error) {
        console.log(error);
    }
});

//Login Part
router.post("/signin", async (req, res) => {
    try {
        const { email, cpassword } = req.body;

        if (!email || !cpassword) {
            return res.status(400).json({ error: " please enter valid credentials" });
        }

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

        const token = userLogin.generateAuthToken();

        res.cookie("signinToken", token, {
            expires: new Date(Date.now()   25892000000),
            httpOnly: true,
        });

        if (userLogin) {
            const isMatch = await bcrypt.compare(cpassword, userLogin.cpassword);

            if (isMatch) {
                return res.status(200).json({ message: "sigin in scuccessfully" });
            } else {
                return res.status(400).json({ error: " Invalid credentials" });
            }
        } else {
            return res.status(400).json({ error: "  Invalid credentials " });
        }
    } catch (error) {
        console.log(error);
    }
});

//watchlistpage
router.get("/watchlist", auth, (req, res) => {
    console.log("  this is jwt token test  "   req.cookies.signinToken);
    res.send(req.rootuser);
    console.log(req.rootuser);
});

module.exports = router;

On newUserSchema.js:

const mongoose = require("mongoose");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");

const newUserSchema = new mongoose.Schema({
    username: {
        type: String,
        required: true,
    },
    email: {
        type: String,
        required: true,
    },
    cpassword: {
        type: String,
        required: true,
    },
    retypePassword: {
        type: String,
        required: true,
    },
    tokens: [
        {
            token: {
                type: String,
                required: true,
            },
        },
    ],
});

newUserSchema.pre("save", async function (next) {
    if (this.isModified("cpassword")) {
        this.cpassword = await bcrypt.hash(this.cpassword, 12);
        this.retypePassword = await bcrypt.hash(this.retypePassword, 12);
    }
    next();
});

newUserSchema.methods.generateAuthToken = async function () {
    try {
        let token = jwt.sign({ _id: this._id }, process.env.SECRETKEY);
        this.tokens = this.tokens.concat({ token: token });
        await this.save();
        return token;
    } catch (error) {
        console.log(error);
    }
};

const User = mongoose.model("newUser", newUserSchema);

module.exports = User;

On auth.js (this is also my middleware)

    const jwt = require("jsonwebtoken");
const User = require("../model/newUserSchema");

const Auth = async (req, res, next) => {
    try {
        console.log(JSON.stringify(req.cookies.signinToken)   "  this is jwt token test");
        const token = req.cookies.signinToken;
        const verifytoken = jwt.verify(token, process.env.SECRETKEY);

        const rootuser = await User.findOne({ _id: verifytoken._id, "tokens.token": token });

        if (!rootuser) {
            throw new Error("user not found");
        }

        req.token = token;
        req.rootuser = rootuser;
        req.UserID = rootuser._id;

        next();
    } catch (error) {
        res.status(401).send("Unauthorized access");
        console.log(error);
    }
};

module.exports = Auth;

The API call result in postman

postmanimg

The terminal error :

terminalimg

when I try to console log on route.js inside Signin page i see promise pending

  const token = userLogin.generateAuthToken();
        console.log(token);
        res.cookie("signinToken", token, {
            expires: new Date(Date.now()   25892000000),
            httpOnly: true,
        });

enter image description here

Could you please help to correct the error also please let me know why is this error coming?

Thanks a million in advance for any tips or suggestions.

CodePudding user response:

Hi Thanks for the help

I just saw that my token was returning a promise, I did not add the keyword await before the token other thing was I was trying to access it before the validation, hence it was showing me nodata and error.

Please see the correct code below:

//Login Part
router.post("/signin", async (req, res) => {
    try {
        const { email, cpassword } = req.body;

        if (!email || !cpassword) {
            return res.status(400).json({ error: " please enter valid credentials" });
        }

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

        if (userLogin) {
            const isMatch = await bcrypt.compare(cpassword, userLogin.cpassword);

            const token = await userLogin.generateAuthToken();
            console.log(token);
            res.cookie("signinToken", token, {
                expires: new Date(Date.now()   25892000000),
                httpOnly: true,
            });

            if (isMatch) {
                return res.status(200).json({ message: "sigin in scuccessfully" });
            } else {
                return res.status(400).json({ error: " Invalid credentials" });
            }
        } else {
            return res.status(400).json({ error: "  Invalid credentials " });
        }
    } catch (error) {
        console.log(error);
    }
});

I hope this might help other learners too.

Thanks.

  • Related