jaredhanson / passport-local

Username and password authentication strategy for Passport and Node.js.
https://www.passportjs.org/packages/passport-local/?utm_source=github&utm_medium=referral&utm_campaign=passport-local&utm_content=about
MIT License
2.73k stars 498 forks source link

done function with null user returns an error #191

Open flahol opened 2 years ago

flahol commented 2 years ago

I have an express 4, sequelize, passport, ES6 server. When I authenticate a user with the right password, it works. But when I have a bad user or a wrong password the done(null,false,{message:"error"}) throws an error :

TypeError: Cannot convert undefined or null to object
POSThttp://localhost:8080/api/v2/login

auth.service.js

import passport from "passport";
import { ExtractJwt, Strategy as JwtStrategy } from "passport-jwt";
import { Strategy as LocalStrategy } from "passport-local";

import userModel from "../modules/user/user.model";
import { db } from "../config/database.js";
import bcrypt from "bcryptjs";

const User = userModel(db.sequelize, db.Sequelize);

const localOptions = {
  usernameField: "email",
  passwordField: "password",
  session: false,
};

const jwtOptions = {
  jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
  secretOrKey: process.env.JWT_SECRET,
};

const localStrategy = new LocalStrategy(localOptions, function (email, password, done) {
  User.findOne({ where: { email: email }, raw: true })
    .then((user) => {
      if (!user) {
        return done(null, false, { message: `Cannot find contact with email=${email}.` });
      }

      bcrypt.compare(password, user.password).then((r) => {
        if (!r) {
          return done(null, false, { message: "Invalid password" });
        }
      });

      return done(null, user);
    })
    .catch((err) => {
      done(err, null, {
        message: "Error connecting to database",
      });
    });
});

passport.use(localStrategy);

export const authLocal = passport.authenticate("local", { session: false });

routes.js

import { Router } from "express";
import * as userController from "./user.controller.js";
import { authLocal } from "../../services/auth.services.js";

const routes = new Router();

routes.post("/login", authLocal, userController.login);

export default routes;

If I change return done(null, false, { message: "Invalid password" }); with return done(null, {name:"test"} , { message: "Invalid password" }); it seems to go for the next callback userController.login but it is not what I want. Do I need to add a failure route ? I can't find how to solve this issue.