0

I am trying to authenticate using jwt but for some reason the static method named isCorrectPassword is always undefined in the user instance.

If I console.log user then I see the has, _id etc so the db connection and find works but not the static method. I am not sure what is wrong here.

// User schema
const { Schema } = require("mongoose")
const bcrypt = require("bcrypt")

const UserSchema = new Schema({
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true }
})

UserSchema.statics.isCorrectPassword = function(password, callback) {
  console.log(callback)
  bcrypt.compare(password, this.password).then(function(err, same) {
    if (err) {
      callback(err)
    } else {
      callback(err, same)
    }
  })
}

module.exports = UserSchema


// User model
const mongoose = require("mongoose")
const bcrypt = require("bcrypt")
const UserSchema = require("../schemas/user")

const saltRounds = 10

UserSchema.pre("save", function(next) {
  // Check if document is new or a new password has been set
  if (this.isNew || this.isModified("password")) {
    // Saving reference to this because of changing scopes
    const document = this
    bcrypt.hash(document.password, saltRounds, function(err, hashedPassword) {
      if (err) {
        next(err)
      } else {
        document.password = hashedPassword
        next()
      }
    })
  } else {
    next()
  }
})

module.exports = mongoose.model("User", UserSchema)


const jwt = require("jsonwebtoken")
const { db } = require("../db")

const secret = process.env.REACT_APP_AUTH_SECRET

function userAuth(router) {
  router.post("/authenticate", async (req, res) => {
    const { email, password } = req.body

    const Users = db.collection("users")

    Users.findOne({ email }, function(err, user) {
      if (err) {
        console.error(err)
        res.status(500).json({
          error: "Internal error please try again"
        })
      } else if (!user) {
        res.status(401).json({
          error: "Incorrect email or password"
        })
      } else {
        user.isCorrectPassword(password, function(err, same) {
          if (err) {
            res.status(500).json({
              error: "Internal error please try again"
            })
          } else if (!same) {
            res.status(401).json({
              error: "Incorrect email or password"
            })
          } else {
            // Issue token
            const payload = { email }
            const token = jwt.sign(payload, secret, {
              expiresIn: "1h"
            })
            res.cookie("token", token, { httpOnly: true }).sendStatus(200)
          }
        })
      }
    })
  })
}

module.exports = userAuth
Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
AspiringCanadian
  • 1,595
  • 6
  • 24
  • 43
  • *"... is always undefined in the user instance."* - Which is completely correct since **static** methods are for the **Model** and NOT the `instance`. If you want to work with "instance data" from a `new` or a `find()`("like") result then you want **`methods`** instead. – Neil Lunn Mar 23 '19 at 04:52
  • replacing .statics with .methods returns the same result, undefined. – AspiringCanadian Mar 23 '19 at 04:57
  • 1
    Not if you take more than 5 minutes to literally just replace `statics` with `method` in your code. Read the responses, and look at the documentation in order to understand the differences of when you use one over the other. If everything was answered by "search and replace" then that would be just peachy! But in the real world you actually need to stop and learn things when something goes wrong. Now you know where to look. Take some time, since you probably won't absorb this in just a few minutes But it's still the same answer. – Neil Lunn Mar 23 '19 at 05:01

0 Answers0