bcrypt-nodejs compare function always return false - node.js

I'm having problem with bcrypt-nodejs' compare function.
The compare function is returning the false value even the password is the right one.
I've tried everything I could and I don't know the what is wrong with my code.
My Folder Structure
src
-config
-config.js
-controller
-AuthenticationController.js
-models
-index.js
-User.js
-policies
-AuthenticationControllerPolicy.js
app.js
routes.js
package.json
I think the problem is with the User.js in models folder.
User.js
const Promise = require('bluebird')
const bcrypt = Promise.promisifyAll(require('bcrypt-nodejs'))
function hashPassword (user, options) {
const SALT_FACTOR = 8
if (!user.changed('password')) {
return
}
return bcrypt
.genSaltAsync(SALT_FACTOR)
.then(salt => bcrypt.hashAsync(user.password, salt, null))
.then(hash => {
user.setDataValue('password', hash)
})
}
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
}, {
hooks: {
beforeCreate: hashPassword,
beforeUpdate: hashPassword,
beforeSave: hashPassword
}
})
User.prototype.comparePassword = function (password) {
return bcrypt.compareAsync(password, this.password)
}
User.associate = function (models) {
}
return User
}
AuthenticationController.js
const {User} = require('../models')
const jwt = require('jsonwebtoken')
const config = require('../config/config')
function jwtSignUser (user) {
const ONE_WEEK = 60 * 60 * 24 * 7
return jwt.sign(user, config.authentication.jwtSecret, {
expiresIn: ONE_WEEK
})
}
module.exports = {
async register (req, res) {
try {
const user = await User.create(req.body)
const userJson = user.toJSON()
res.send({
user: userJson
})
} catch (err) {
res.status(400).send({
error: 'This email account is already in use.'
})
}
},
async login (req, res) {
try {
const {email, password} = req.body
const user = await User.findOne({
where: {
email: email
}
})
console.log('user BEFORE', user)
if (!user) {
console.log('!user')
return res.status(403).send({
error: 'The login information was incorrect'
})
}
console.log('user AFTER', user)
const isPasswordValid = await user.comparePassword(password)
console.log('isPasswordValid BEFORE : ', isPasswordValid)
if (!isPasswordValid) {
console.log('isPasswordValid AFTER : ', isPasswordValid)
return res.status(403).send({
error: 'The login information was incorrect'
})
}
const userJson = user.toJSON()
res.send({
user: userJson,
token: jwtSignUser(userJson)
})
} catch (err) {
res.status(500).send({
error: 'An error has occured trying to log in'
})
}
}
}
route.js
const AuthenticationController = require('./controller/AuthenticationController')
const AuthenticationControllerPolicy = require('./policies/AuthenticationControllerPolicy')
module.exports = (app) => {
app.post('/register',
AuthenticationControllerPolicy.register,
AuthenticationController.register)
app.post('/login',
AuthenticationController.login)
}
You can also check the repo if you want.
GitHubRepo

The usage of bcrypt-nodejs appears to be correct. I would verify that both the password coming in and the hash in the database are what you expect them to be (particularly inside the comparePassword function) to rule out if it's a data issue or not.

Related

Check if user exists in router before creation in database with Sequelize

I have a function to check if a user exists, and a function to create a new user in my User model.
What I want to do is call them in the router to check if a user with the email adress in req.body already exists.
If it does, I want to return a message, and if not, I want to create the user.
When I try to call the route in Postman, I get this error in node console :
node_modules/express/lib/response.js:257
var escape = app.get('json escape')
TypeError: Cannot read properties of undefined (reading 'get')
User model :
const Sequelize = require("sequelize");
const connexion = require("../database");
const User = connexion.define(
"users",
{
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
email: {
type: Sequelize.STRING(100),
allowNull: false,
},
password: {
type: Sequelize.STRING(100),
allowNull: false,
},
},
{
freezeTableName: true
}
);
function checkUser(userEmail) {
const findUser = User.findOne({ where: { userEmail } }).catch((err) => {
console.log(err);
});
if (findUser) {
return res.json({ message: "Cette adresse email est déjà enregistrée" });
} else {
return false;
}
}
function createUser(userData) {
console.log(userData);
User.create(userData)
.then((user) => {
console.log(user);
})
.catch((err) => {
console.log(err);
});
}
module.exports = { createUser, checkUser };
user controller :
const createUser = require("../models/User");
const bcrypt = require("bcrypt");
const saltRounds = 10;
addUser = async (req, res) => {
try {
const userData = req.body;
console.log(req.body);
bcrypt.hash(userData.password, saltRounds, async function (err, hash) {
userData.password = hash;
const newUser = await createUser(req.body);
res.status(201).json({ newUser });
});
} catch (err) {
console.log(err);
res.status(500).json("Server error");
}
};
module.exports = addUser;
user router :
const express = require("express");
const router = express.Router();
const addUser = require("../controllers/userController");
const { checkUser } = require("../models/User");
router.post("/", async (req, res) => {
const { email } = req.body;
const alreadyExists = await checkUser(email);
if (!alreadyExists) {
addUser(req.body);
}
});
module.exports = router;
EDIT : Finally I'm trying a more simple way. I will do the check part directly into the createUser function.
But now, it creates the user even if the email already exists ^^
async function createUser(userData) {
console.log(userData);
const findUser = await User.findOne({ where: userData.email }).catch(
(err) => {
console.log(err);
}
);
findUser
? console.log(findUser)
: User.create(userData)
.then((user) => {
console.log(user);
})
.catch((err) => {
console.log(err);
});
}
i think the problem is with this part you are trying to use res but it doesn't exist in your checkUser function
if (findUser) {
return res.json({ message: "Cette adresse email est déjà enregistrée" });
} else {
return false;
}
try this instead
if (findUser) {
return true });
} else {
return false;
}
UPDATE to fix the problem of user creation if it already exists
async function createUser(userData) {
console.log(userData);
const findUser = await User.findOne({ where: userData.email }).catch(
(err) => {
console.log(err);
}
);
if(!findUser){
findUser
? console.log(findUser)
: User.create(userData)
.then((user) => {
console.log(user);
})
.catch((err) => {
console.log(err);
});
}
}
Problem solved by doing this (thanks super sub for your help):
async function createUser(userData) {
console.log(userData);
const email = userData.email;
const findUser = await User.findOne({ where: { email } }).catch((err) => {
console.log(err);
});
if (!findUser) {
User.create(userData)
.then((user) => {
console.log(user);
})
.catch((err) => {
console.log(err);
});
}
}

TypeError: Cannot read property 'jwtoken' of undefined at Authenticate

I am trying to authenticate the user using jwt and found this error. This is a MERN project and I had to verify the user whose data I have stored in MongoDb before showing a secret page.
Other errors which VSCode is highlighting are:
1.When I hover on ._id (authentication.js)
const rootUser=await User.findOne({_id:verifyToken._id,"tokens.token":token})
Property '_id' does not exist on type 'string | JwtPayload'.
2.When I hover on req.rootUser(app.js)
res.send(req.rootUser)
Property 'rootUser' does not exist on type 'Request<{}, any, any, ParsedQs, Record<string, any>>
My code looks as follows:
app.js
const mongoose = require('mongoose')
const dotenv = require('dotenv')
const bcrypt = require('bcryptjs')
const jwt=require('jsonwebtoken')
const app = express()
const router = express.Router();
const port = 5000
const authenticate=require("./middleware/authenticate")
dotenv.config({ path: './config.env' })
const DB = process.env.DATABASE;
app.use(express.json());
const User = require('./model/userSchema')
mongoose
.connect(DB, {
useUnifiedTopology: true,
useNewUrlParser: true,
})
.then(() => console.log('Database connected.'))
.catch(err => console.log(err));
app.get('/', (req, res) => {
res.send('Hello World!')
console.log("hey")
})
app.post('/register', async (req, res) => {
const { name, email, work, phone, password, cpassword } = req.body;
if (!name || !email || !work || !phone || !password || !cpassword) {
return res.status(422).json({ error: "Form Not Properly Filled" });
}
try {
const userExist = await User.findOne({ email: email })
if (userExist) {
return res.status(422).json({ error: "Email ALready Exists" })
}
else if (password != cpassword) {
return res.status(422).json({ error: "Password does not match" })
}
else {
const user = new User({ name, email, work, phone, password, cpassword })
await user.save()
res.status(201).json({ message: "user registered successfully" })
}
} catch (error) {
console.log(error);
}
})
//login route
app.post('/signin', async (req, res) => {
try {
let token;
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({ error: "Please fill the data correctly" })
}
const userLogin = await User.findOne({ email: email })
console.log(userLogin);
if (userLogin) {
const isMatch = await bcrypt.compare(password, userLogin.password)
token = await userLogin.generateAuthToken();
console.log(token)
res.cookie("jwtoken",token,{
expires:new Date(Date.now()+25892000000),
httpOnly:true
})
if (!isMatch) {
res.status(400).json({ error: "Invalid Credentials" })
}
else {
res.status(200).json({ message: "Login Success" })
}
}
else {
res.status(400).json({ error: "Invalid Credentials" })
}
} catch (error) {
console.log(error)
}
})
//about page request
app.get('/about',authenticate, (req, res) => {
console.log("About")
res.send(req.rootUser)
})
app.get('/forget', (req, res) => {
res.cookie("harsh","test")
res.send('Forget World!')
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
authenticate.js
const User=require("../model/userSchema")
const Authenticate=async (req,res,next)=>{
try {
console.log(req.cookies)
const token=req.cookies.jwtoken;
console.log("below")
const verifyToken =jwt.verify(token,process.env.SECRET_KEY)
console.log(verifyToken)
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 : No token provided')
console.log(error)
}
}
module.exports=Authenticate;
userSchema.js
const mongoose=require('mongoose')
const bcrypt=require('bcryptjs')
const jwt=require('jsonwebtoken')
const userSchema=new mongoose.Schema({
name:{
type:String,
required:true,
},
email:{
type:String,
required:true,
},
phone:{
type:String,
required:true,
},
work:{
type:String,
required:true,
},
password:{
type:String,
required:true,
},
cpassword:{
type:String,
required:true,
},
tokens:[
{
token:{
type:String,
required:true,
}
}
]
})
userSchema.pre('save' , async function(next){
console.log("inside hash")
if(this.isModified('password')){
this.password=await bcrypt.hash(this.password,12)
this.cpassword=await bcrypt.hash(this.cpassword,12)
}
next();
})
userSchema.methods.generateAuthToken = async function(){
try {
let token =jwt.sign({_id:this._id},process.env.SECRET_KEY)
this.tokens=this.tokens.concat({token : token})
await this.save();
return token
} catch (error) {
console.log(error)
}
}
const User=mongoose.model('USER',userSchema);
module.exports=User;
1. GENERATE JWT TOKEN WHEN USER LOGIN
Generate Token and Send this token with a response...
router.post("/login", async (req, res) => {
try {
// checking username
const user = await User.findOne({ email: req.body.email });
!user && res.status(401).json("Wrong Username");
// checking password
const bytes = CryptoJS.AES.decrypt(user.password, process.env.SECRET_KEY);
const originalPassword = bytes.toString(CryptoJS.enc.Utf8);
// If password not match return respond
originalPassword !== req.body.password &&
res.status(401).json("Wrong Password");
// Creating Json Web Token
const accessToken = jwt.sign(
{ id: user._id, isAdmin: user.isAdmin },
process.env.SECRET_KEY,
{ expiresIn: "5d" }
);
// stop sending password to respond
const { password, ...info } = user._doc;
// Returning User(info) , also sending accessToken
res.status(200).json({ ...info, accessToken });
} catch (err) {
res.status(500).json(err);
}
});
2. VERIFY TOKEN MIDDLEWARE
Create this verify token function use as a MIDDLEWARE in your routes...
const jwt = require("jsonwebtoken");
function verify(req, res, next) {
const authHeader = req.headers.token;
if (authHeader) {
const token = authHeader.split(" ")[1];
jwt.verify(token, process.env.SECRET_KEY, (err, user) => {
if (err) res.status(403).json("Token is not valid");
req.user = user;
next();
});
} else {
return res.status(402).json("You are not authorized");
}
}
module.exports = verify;
3. VERIFY-IN ROUTES AS AN MIDDLEWARE
const verify = require("../verifyToken");
// CREATE
router.post("/", verify, async (req, res) => {
if (req.user.isAdmin) {
const newList = new List(req.body);
try {
const savedList = await newList.save();
res.status(201).json(savedList);
} catch (error) {
res.status(500).json(err);
}
} else {
res.status(403).json("You are not allowed!");
}
});
// DELETE
router.delete("/:id", verify, async (req, res) => {
if (req.user.isAdmin) {
try {
await List.findByIdAndDelete(req.params.id);
res.status(201).json("The list has been deleted");
} catch (err) {
res.status(500).json(err);
}
} else {
res.status(403).json("You are not allowed!");
}
});
CONCLUSION:-
Create a token with jwt.sign when user login...
Create a verify function in the root directory export this function...
Require this function in routes file use as a middleware...

How to implement Node.JS model using Sequelize

I have a project with the below Model, Controller, and Route File for user. I am wanting to implement sequelize, which I have managed to partially achieve using the account files below, however, I am struggling to work out how to implement logging in and ensuring a request has a valid token usijng user.ensureToken which would become account.ensureToken.
I'm fairly new to Node.Js so I'm not even sure where to start
user.model.js
const bcrypt = require('bcrypt');
const sql = require("./db.js");
const HashBits = require("../config/auth.config.js");
const faker = require('faker');
// constructor
const User = function(user) {
this.first_name = user.first_name;
this.last_name = user.last_name;
this.mob_no = user.mob_no;
this.user_name = user.user_name;
this.password = user.password;
};
User.create = (newUser, result) => {
bcrypt.hash(newUser.password, HashBits.saltRounds, (err, hash) => {
newUser.password = hash;
sql.query("INSERT INTO users SET ?", newUser, (err, res) => {
if (err) {
// console.log("error: ", err);
result(err, null);
return;
}
newID = res.insertId;
// console.log("created user: ", { id: res.insertId, ...newUser });
result(null, { id: res.insertId, ...newUser });
});
});
};
User.authenticate = (user,result) => {
// sql.query(`SELECT * FROM customers WHERE id = ${customerId}`, (err, res) => {
sql.query(`SELECT * FROM users WHERE user_name = '${user.user_name}'`, (err, res) => {
// sql.query("SELECT * FROM users ", (err, res) => {
if (err) {
// console.log("error: ", err);
result(err, null);
return;
}
if(res.length !== 1){
// console.log("error: found multiple users");
result("error: found multiple users", null);
return;
}
// console.log("Found user: ",res[0]);
bcrypt.compare(user.password, res[0].password, function(err, res2) {
if(res2){
// console.log("Yes");
result(null,res[0]);
}else{
// console.log("On ya bike");
result("ERROR",null);
// return;
}
});
});
};
module.exports = User;
user.controller.js
const User = require("../models/user.model.js");
var jwt = require("jsonwebtoken");
const config = require("../config/auth.config.js");
// Create and Save a new User
exports.create = (req, res) => {
// Validate request
if (!req.body) {
res.status(400).send({
message: "Content can not be empty!"
});
}
// Create a User
const user = new User({
first_name: req.body.first_name,
last_name: req.body.last_name,
mob_no: req.body.mob_no,
user_name: req.body.user_name,
password: req.body.password
});
// Save User in the database
User.create(user, (err, data) => {
if (err)
res.status(500).send({
message:
err.message || "Some error occurred while creating the User."
});
else res.send(data);
});
};
exports.authenticate = (req,res) => {
if (!req.body) {
res.status(400).send({
message: "Content can not be empty!"
});
}
const user = new User({
user_name: req.body.user_name,
password: req.body.password
});
User.authenticate(user, (err,data) => {
if(err)
res.status(500).send({
message:
err.message || "Some error occurred while authenticating the User."
});
else {
var token = jwt.sign({ id: user.id }, config.secret, {
expiresIn: 86400 // 24 hours
});
// res.send(data);
res.status(200).send({
id: data.id,
username: data.user_name,
accessToken: token
});
}
});
};
exports.ensureToken = (req, res, next) => {
let token = req.headers["x-access-token"];
if (!token) {
return res.status(403).send({
message: "No token provided!"
});
}
jwt.verify(token, config.secret, (err, decoded) => {
if (err) {
return res.status(401).send({
message: "Unauthorized!"
});
}
req.userId = decoded.id;
next();
});
}
user.routes.js
module.exports = app => {
const users = require("../controllers/user.controller.js");
// Create a new User
app.post("/User", users.create);
// Login
app.post("/User/Login", users.authenticate);
};
account.model.js
const bcrypt = require("bcrypt");
module.exports = (sequelize, Sequelize) => {
const Account = sequelize.define("account", {
firstName: {
type: Sequelize.STRING
},
username: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING,
set(value){
const hash = bcrypt.hashSync(value, 10);
this.setDataValue('password', hash);
}
}
});
return Account;
};
account.controller.js
const db = require("../models");
const Account = db.accounts;
const Op = db.Sequelize.Op;
var jwt = require("jsonwebtoken");
const config = require("../config/auth.config.js");
// Create and Save a new New
exports.create = (req, res) => {
// Validate request
if (!req.body.username) {
res.status(400).send({
message: "Content can not be empty!"
});
return;
}
// Create a Site
const account = {
firstName: req.body.firstName,
username: req.body.username,
password: req.body.password
};
Account.create(account)
.then(data => {
res.send(data);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while creating the Account."
});
});
};
exports.authenticate = (req,res) => {
if (!req.body) {
res.status(400).send({
message: "Content can not be empty!"
});
}
const account = new Account({
username: req.body.username,
password: req.body.password
});
};
account.routes.js
module.exports = app => {
const accounts = require("../controllers/account.controller.js");
var router = require("express").Router();
app.post("/account", accounts.create);
app.post("/account/Login", accounts.authenticate);
};
you need to use jwt token for access token as you said and you are bcrypt password in model file which will be security issue you have to bcrypt password as soon as it comes in request I have implemented it in my answer remove code of password bcrypt from your model file
you have to import in your account.controller.js
const db = require("../models");
const User = db.user;
require('dotenv').config();
const Op = db.Sequelize.Op;
const errors = require('../config/errors');
const error = errors.errors;
var jwt = require("jsonwebtoken");
var bcrypt = require("bcryptjs");
module.exports = {
signup: async (req, res) => {
if (!req.body.first_name|| !req.body.lastt_name || !req.body.password) {
return res.status(200).send(error.MANDATORY_FIELDS);
}
try {
// Save User to Database
User.create({
name: req.body.name,
email: req.body.email,
mo_no: req.body.mo_no,
city: req.body.city,
password: bcrypt.hashSync(req.body.password, 8),
user_type: "admin"
}).then(function (user) {
return res.status(200).send(error.OK)
})
.catch(function (err) {
console.log(err);
return res.status(500).send(error.SERVER_ERROR)
});
} catch (e) {
console.log(e);
return res.status(500).send(error.SERVER_ERROR)
}
},
signin: async (req, res) => {
if (!req.body.email || !req.body.password) {
return res.status(200).send(error.MANDATORY_FIELDS);
}
User.findOne({
where: {
email: req.body.email
}
}).then(function (user) {
if (!user) {
return res.status(404).send(error.USER_NOT_PRESENT);
}
const passwordIsValid = bcrypt.compareSync(
req.body.password,
user.password
);
if (!passwordIsValid) {
return res.status(422).send(error.PASSWORD_MISSMATCH, {
accessToken: null
});
}
const token = jwt.sign({ id: user.id, first_name: user.first_name },
process.env.secret, {
expiresIn: 86400 // 24 hours
});
const authorities = [];
return res.status(200).send({
id: user.id,
name: user.name,
email: user.email,
accessToken: token
});
});
})
.catch(function (err) {
console.log(err)
return res.status(500).send(error.SERVER_ERROR);
});
}
}
than you have to create a separate folder for authorization like authorize.js or authJwt.js where you have to check is token is valid or not put this code in authorize.js
at decoding time secret token or password also needed which you have in .env file
const jwt = require("jsonwebtoken");
verifyToken = (req, res, next) => {
let token = req.headers["x-access-token"];
if (!token) {
return res.status(403).send(error.TOKEN_NOT_PROVIDED);
}
jwt.verify(token, process.env.secret, (err, decoded) => {
if (err) {
return res.status(401).send(error.UNAUTHORIZED);
}
req.first_name= decoded.first_name;
req.id = decoded.user_id
next();
});
};
const authJwt = {
verifyToken: verifyToken
};
module.exports = authJwt;
than you have to import authorize.js file in your routes whenever you want like this
const authorize = require('../authorize.js');
module.exports = app => {
const accounts = require("../controllers/account.controller.js");
var router = require("express").Router();
app.post("/account", accounts.create);
app.post("/account/Login",
authorize.verifyToken,accounts.authenticate);
};
it will be more effective if you genreate access token at signin time

TypeError: Cannot read property 'authenticate' of null

I am working in user signin authentication in backend. Whenever I hit send request from postman it shows error as
TypeError: Cannot read property 'authenticate' of null
at /home/saru/mernbootcamp/projbackend/controllers/auth.js
I had check this error in stackoverflow but the solution doesn't match my case
controllers/auth.js
`const User = require("../models/user");
//express-validator
const { check, validationResult } = require('express-validator');
var jwt = require('jsonwebtoken');
var expressJwt = require('express-jwt');
const dotenv = require("dotenv")
const config = dotenv.config({ path: './routes/.env' });
//user object creation for class/model User
const user = new User(req.body);
exports.signin = (req, res) => {
const errors = validationResult(req);
const { email, password } = req.body;
if (!errors.isEmpty()) {
return res.status(422).json({
error: errors.array()[0].msg
});
}
User.findOne({ email }, (err, user) => {
if (err) {
return res.status(400).json({
error: "USER email does not exists"
});
}
console.log(password);
if (!user.authenticate(password)) {
return res.status(401).json({
error: "Email and password do not match"
});
}
//create token
const token = jwt.sign({ _id: user._id }, process.env.SECRET);
//put token in cookie
res.cookie("token", token, { expire: new Date() + 9999 });
//send response to front end
const { _id, name, email, role } = user;
return res.json({ token, user: { _id, name, email, role } });
});
};
`
models/user.js
`var mongoose = require("mongoose");
const crypto = require("crypto");
const uuidv1 = require("uuid/v1");
var userSchema = new mongoose.Schema(
{
email: {
type: String,
trim: true,
required: true,
unique: true
},
encry_password: {
type: String,
required: true
},
salt: String,
},
{ timestamps: true }
);
userSchema
.virtual("password")
.set(function (password) {
this._password = password;
this.salt = uuidv1();
this.encry_password = this.securePassword(password);
})
.get(function () {
return this._password;
});
userSchema.method = {
authenticate: function (plainpassword) {
return this.securePassword(plainpassword) === this.encry_password;
},
securePassword: function (plainpassword) {
if (!password) return "";
try {
return crypto
.createHmac("sha256", this.salt)
.update(plainpassword)
.digest("hex");
} catch (err) {
return "";
}
}
};
module.exports = mongoose.model("User", userSchema);
`
In controllers/auth.js
Replace the if(err) with if(err || !user) in the findOne() method
You can use this code:
User.findOne({email}, (err, user) => {
if (err || !user) {
return res.status(400).json({
error: "USER email does not exists"
})
}
});
Replace if (err) with if (err || !user) and use return before res.status

Node.js > 'findOne' of undefined < LocalStrategy from Passport

I used Passport to create login.
However, I get:
TypeError: Cannot read property 'findOne' of undefined
when trying to login.
After debugging, I confirmed that user was undefined after async of localStrategy.js.
I think all the actions are perfect, but there is a problem with my code.
Can I tell you where I made the mistake?
passport/index.js
const local = require('./localStrategy');
const { User } = require('../model/user');
module.exports = (passport) => {
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
User.findOne({ id: id })
.then((user) => done(null, user))
.catch((err) => done(err));
});
local(passport);
};
passport/localStrategy.js
const LocalStrategy = require('passport-local').Strategy;
const { User } = require('../model/user');
module.exports = (passport) => {
passport.use(
new LocalStrategy(
{
usernameField: 'email',
passwordField: 'password'
},
async (email, password, done) => {
try {
const exUser = await User.findOne({ email: email });
if (exUser) {
const result = await bcrypt.compare(password, exUser.password);
if (result) {
done(null, exUser);
} else {
done(null, false, { message: 'failed.' });
}
} else {
done(null, false, { message: 'failed.' });
}
} catch (err) {
console.error(err);
done(err);
}
}
)
);
};
routes/user.js
const express = require('express');
const router = express.Router();
const { isLoggedIn, isNotLoggedIn } = require('./middleware');
const usersController = require('../controller/users_controller');
router.get('/login', isNotLoggedIn, usersController.user_login);
controller/users_controller.js
const User = require('../model/user');
const bcrypt = require('bcrypt');
const passport = require('passport');
exports.user_login = (req, res, next) => {
passport.authenticate('local', (authError, user, info) => {
if (authError) {
console.error(authError);
return next(authError);
}
if (!user) {
return res.send("not user.")
}
return req.login(user, (loginError) => {
if (loginError) {
console.error(loginError);
return next(loginError);
}
return res.send("login successfully")
});
})(req, res, next);
};
model/user.js
const mongoose = require('mongoose');
let UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
require: true
},
createAt: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('User', UserSchema);
const { User } = require('../model/user');
This code return User = undefined
Can you show code in '../model/user'?
Are you export with:
module.exports = {
User: your_user
}
?
If you use:
module.exports = User;
you should call
const User = require('../model/user');
instead of:
const { User } = require('../model/user');
or you can change export in '../model/user':
module.exports = {
User: your_user
}
It should be _id not id in your query
passport/index.js
User.findOne({ _id: id })
.then((user) => done(null, user))
.catch((err) => done(err));
});
In passport/localStrategy file correct import of Model
const User = require('../model/user');

Resources