JWT token signup and signin express API

Issue

I am trying postman for signup a user, {"firstName": "John", "lastName":"zoe", "email":"[email protected]", "password":"123465"} but the postman gives me this 500 error: {
"message": "Something went wrong"
},

I could not figure out is my logic wrong, or something is missing, I did not use the validator package, as I am not sure how to use it, is that the problem? can anyone pls help?

here is my code, in the server.js file:

const express = require("express");
const env = require("dotenv");
const { response } = require("express");
const app = express();
const mongoose = require("mongoose");

//routes
const authRoutes = require("./routes/auth");
const adminRoutes = require("./routes/adminauth");
const categoryRoutes = require("./routes/category");

//enviorment variables
env.config();

app.use(express.json());

mongoose
  .connect(
    `mongodb+srv://${process.env.MONGO_DB_USER}:${process.env.MONGO_DB_PASSWORD}@cluster0.h28xczp.mongodb.net/${process.env.MONGODB_DATABASE}?retryWrites=true&w=majority`
  )
  .then(() => {
    console.log("Database connection established");
  });

app.use("/api", authRoutes);
app.use("/api", adminRoutes);
app.use("/api", categoryRoutes);

app.listen(process.env.PORT, () => {
  console.log(`server is running at ${process.env.PORT}`);
});

In my routes file:

const express = require("express");
const router = express.Router();
const { signupUser, loginUser } = require("../controller/auth");
const { auth, userMiddleware, adminMiddleware } = require("../middleware/auth");

//login route
router.post("/login", loginUser);

//signup route
router.post("/signup", signupUser);

module.exports = router;

Middleware file:

const jwt = require("jsonwebtoken");
const User = require("../models/user");

exports.auth = (req, res, next) => {
  try {
    const token = req.header.authorization.split("")[1];
    const isCustomAuth = token.length < 500;

    let decodeData;
    if (token && isCustomAuth) {
      decodeData = jwt.verify(token, env.Process.JWT_SECRET);
      req.UserId = decodeData?.id;
    } else {
      decodeData = jwt.decode(token);
      req.UserId = decodeData?.sub;
    }
    next();
  } catch (error) {}
};

exports.userMiddleware = (req, res, next) => {
  if (req.user.role !== "user") {
    return res.status(400).json({ message: "User access denied" });
  }
  next();
};

exports.adminMiddleware = (req, res, next) => {
  if (req.user.role !== "admin") {
    return res.status(400).json({ message: "Access denied" });
  }
  next();
};

In my controller file:

const User = require("../models/user");
const jwt = require("jsonwebtoken");
const bcrypt = require("bcrypt");

exports.loginUser = async (req, res) => {
  const { email, password } = req.body;
  try {
    const existingUser = await User.findOne({ email });
    if (!existingUser)
      return res.status(400).json({ message: "User does not exists." });

    const isPasswordCorrect = await bcrypt.compare(
      password,
      existingUser.password
    );

    if (!isPasswordCorrect)
      return res.status(400).json({ message: "Invalid credentials." });

    const token = jwt.sign(
      { email: existingUser.email, id: existingUser._id },
      process.env.JWT_SECRET,
      { expiresIn: "3d" }
    );

    res.status(200).json({ result: existingUser, token });
  } catch (error) {
    res.status(500).json({ message: "Something went wrong" });
  }
};

exports.signupUser = async (req, res) => {
  const { firstName, lastName, email, password, confirmPassword } = req.body;
  try {
    const existingUser = await User.findOne({ email });
    if (existingUser)
      return res.status(400).json({ message: "User already exists." });
    if (!password == confirmPassword)
      return res.status(400).json({ message: "Password don't match" });

    const hashedPassword = await bcrypt.hash(password, 12);

    const result = await User.create({
      email,
      password: hashedPassword,
      firstName,
      lastName,
    });

    const token = jwt.sign(
      { email: result.email, id: result._id },
      process.env.JWT_SECRET,
      { expiresIn: "3d" }
    );

    res.status(200).json({ result, token });
  } catch (error) {
    res.status(500).json({ message: "Something went wrong" });
  }
};

My user model file:

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

const userSchema = new mongoose.Schema(
  {
    firstName: {
      type: String,
      required: true,
      trim: true,
    },
    lastName: {
      type: String,
      required: true,
      trim: true,
    },
    email: {
      type: String,
      required: true,
      trim: true,
      unique: true,
    },
    password: {
      type: String,
      required: true,
    },
    id: {
      type: String,
    },
   
  },
  { timestamps: true }
);

module.exports = mongoose.model("User", userSchema);

Solution

In the middleware, this line contains a wrong reference to JWT_SECRET.

decodeData = jwt.verify(token, env.Process.JWT_SECRET);

Should be

decodeData = jwt.verify(token, process.env.JWT_SECRET);

The application throws an unhandled promise rejection error when trying to connect DB, which means it can operate without a DB connection and then throw that error.

So, to handle that, you can rewrite your code to this.


mongoose.connect('mongodb://localhost:27017/usersdb',  // change with your db url
    {
        useNewUrlParser: true,
        useUnifiedTopology: true
    }
)
.then(() => {
    app.use("/api", authRoutes);
    app.listen(process.env.PORT, () => {
        console.log("Server has started on port!", process.env.PORT)
    })
})
.catch(() => { throw new Error(("Connection error")) });

Also, I successfully ran and tested your application on my local machine. Here is a GitHub link; you can compare.

https://github.com/nairi-abgaryan/express-auth

Answered By – Nairi Abgaryan

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published