I’ve provided login/register
system to my page, but I get an error I’ve been struggling with while trying to login
:
TypeError [ERR_INVALID_ARG_TYPE]: The "salt" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined at check (internal/crypto/pbkdf2.js:59:10) at Object.pbkdf2 (internal/crypto/pbkdf2.js:25:5) at validPassword (/Users/krzysztofbialk/TO.DO/config/passwordUtils.js:14:29) at /Users/krzysztofbialk/TO.DO/config/passport_log.js:21:33 at processTicksAndRejections (internal/process/task_queues.js:93:5)
Looks like something here is the problem:
passwordUtils.js
const crypto = require('crypto'); function genPassword(password) { let salt = crypto.randomBytes(32).toString('hex'); let genHash = crypto.pbkdf2Sync(password, salt, 10000, 64, 'sha512').toString('hex'); return { salt: salt, hash: genHash }; }; function validPassword(password, hash, salt) { let hashVerify = crypto.pbkdf2Sync(password, salt, 10000, 64, 'sha512').toString('hex'); return hash === hashVerify; }; module.exports.validPassword = validPassword; module.exports.genPassword = genPassword;
or passport_log.js
const customFields = { usernameField: 'email', passwordField: 'password' }; const verifyCallback = (username, password, done) => { LogUser.findOne({username: username}) .then((user) => { console.log(user) if (!user) {return done(null, false)} const isValid = validPassword(password, user.hash, user.salt); if (isValid) { return done(null, user); } else { return done(null, false); } }) .catch((err) => { done(err); }); }; // LOCAL STRATEGY; it looks good, doesn't it? passport.use(new LocalStrategy(customFields, verifyCallback));
login post route
router.post('/login', passport.authenticate('local', { successRedirect: '/private', failureRedirect: '/login' }));
When I console.log(user) it returns
{ _id: 60cbb580ef0690505762a581, username: 'qw@wp.pl', createdAt: 2021-06-17T20:50:08.570Z, __v: 0 }
But after successful register
it returns
{ _id: 60cbb580ef0690505762a581, username: 'qw@wp.pl', hash: 'b762ebbafb266dab12f71eeabbdae6d53e62e91937c51d99fe1816e6d401379b91495b7db0f56b8143e8607bf72ce2a565c38eeeb1f916cc9c0a85d8e6d3c9fe', salt: '0536b806ac052e5628c74e7ec9fd6b94fb0d1bd4bc0e93fdfdf51ed5b964c581', createdAt: 2021-06-17T20:50:08.570Z }
And in DB
:
_id:ObjectId("60cbb580ef0690505762a581") username:"qw@wp.pl" hash:"b762ebbafb266dab12f71eeabbdae6d53e62e91937c51d99fe1816e6d401379b91495b..." salt:"0536b806ac052e5628c74e7ec9fd6b94fb0d1bd4bc0e93fdfdf51ed5b964c581" createdAt:2021-06-17T20:50:08.570+00:00 __v:0
Why there is hash and salt in user data after register
, but not when tried to login
?
LogUser
schema:
const LogUserSchema = new mongoose.Schema({ name: { type: String }, email: { type: String, // required: true, // unique: true }, password: { type: String, // required: true }, image: { type: String }, createdAt: { type: Date, default: Date.now }, hash: { type: String }, salt: { type: String }});
I have ran out of ideas what’s wrong. Happy to receive any answers!
Advertisement
Answer
Editing to show what turned out to be the right answer:
I think Mongoose removes the hash and salt fields from these kinds of queries by default. So to make your query work you just need to type LogUser.findOne({username: username}, 'username salt hash')
and then the salt and hash should be accessible in the returned document.