Passport local strategy doesnt return user - node.js

My signup and login works completely fine until I want to return user to the front end. User ends up being undefined.
Here is my passport.js
const passport = require('passport');
const localStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const User = mongoose.model('users');
passport.serializeUser((user, done) => {
done(null, user._id)
})
passport.deserializeUser((id, done) =>
User.findById(id).then((user) => {
if (user) {
done(null, user)
} else {
}
})
);
passport.use(new localStrategy((username, password, done) => {
User.findOne({ username: username }, (err, user) => {
console.log(user)
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Username not found' });
}
if (!user.comparePassword(password, user.password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}));
Here is my login route:
const passport = require('passport');
const mongoose = require('mongoose');
const User = mongoose.model('users');
module.exports = (app) => {
app.get('/test', (req, res) => {
res.send('elo')
})
app.post('/login',
passport.authenticate('local', {
successRedirect: '/loginSuccess',
failureRedirect: '/loginFailed',
})
);
app.get('/loginSuccess', (req, res) => {
console.log(req.user)
res.send({ success: true, test:'test', user: req.user })
})
app.get('/loginFailed', (req, res) => {
res.send({ success: false, error: "Incorrect credentials" })
})
};
In passport.js the user exists and should be returnet correctly. It's just getting lost somewhere along the way. Whats funnier, I used the exact same code in my other app few months ago and it worked properly.
Edit:
Turns out it works on postman, so I dont know whats going on now

Related

How to code login (passport) authentication for two different users types? Node.js

I am new to Node.js.
For my application, I have two different type of users being doctors and patient. Currently, I been coding for the login and registration for patients and it works. I starting to code the login for the doctors and it doesn't seem to be working. Below is the passport.js. I watched a video (https://www.youtube.com/watch?v=6FOq4cUdH8k&ab_channel=TraversyMedia) to learn how to code the login and registration.
I think the issue is within the passport.js, I'm not really sure how to code it, when it comes to the second user.
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');
const Patient = require('../models/patients');
module.exports = function(passport) {
passport.use(
new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
Patient.findOne({
email: email
}).then(patient => {
if (!patient) {
return done(null, false, { message: 'That email is not registered' });
}
bcrypt.compare(password, patient.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, patient);
} else {
return done(null, false, { message: 'Password is incorrect' });
}
});
});
})
);
passport.serializeUser(function(patient, done) {
done(null, patient.id);
});
passport.deserializeUser(function(id, done) {
Patient.findById(id, function(err, patient) {
done(err, patient);
});
});
const Doctor = require('../models/doctors');
module.exports = function(passport) {
passport.use(
new LocalStrategy({ usernameField: 'email' }, (demail, dpassword, done) => {
Doctor.findOne({
demail: demail
}).then(doctor => {
if (!doctor) {
return done(null, false, { message: 'That email is not registered' });
}
bcrypt.compare(dpassword, doctor.dpassword, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, doctor);
} else {
return done(null, false, { message: 'Password is incorrect' });
}
});
});
})
);
passport.serializeUser(function(doctor, done) {
done(null, doctor.id);
});
passport.deserializeUser(function(id, done) {
Doctor.findById(id, function(err, doctor) {
done(err, doctor);
});
});
}}:
This is my doctor.js in route
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');
const Doctor = require('../models/doctors');
router.get('/doctorregister', (req, res) => res.render('Doctorregister'));
router.get('/doctorlogin', (req, res) => res.render('Doctorlogin'));
module.exports = router;
router.post('/doctorregister', (req, res) => {
const { dname, dqualification, dlocation, dpractice, demail, dmobileno, dpassword, dpassword2 } = req.body;
let errors = [];
if (!dname|| !dqualification || !dlocation || !dpractice || !demail || !dmobileno || !dpassword || !dpassword2) {
errors.push({ msg: 'Please enter all fields' });
}
if (dpassword != dpassword2) {
errors.push({ msg: 'Passwords do not match' });
}
if (dpassword.length < 6) {
errors.push({ msg: 'Password must be at least 6 characters' });
}
if (errors.length > 0) {
res.render('doctorregister', {
errors,
dname,
dqualification,
dlocation,
dpractice,
demail,
dmobileno,
dpassword,
dpassword2
});
} else {
Doctor.findOne({ demail: demail }).then(doctor => {
if (doctor) {
errors.push({ msg: 'Email already exists' });
res.render('register', {
errors,
dname,
dqualification,
dlocation,
dpractice,
demail,
dmobileno,
dpassword,
dpassword2
});
} else {
const newDoctor = new Doctor({
dname,
dqualification,
dlocation,
dpractice,
demail,
dmobileno,
dpassword,
});
//hashing password in the database
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newDoctor.dpassword, salt, (err, hash) => {
if (err) throw err;
newDoctor.dpassword = hash;
newDoctor.save()
.then(doctor => {
req.flash('success_msg', 'You are now registered and can log in')
res.redirect('/doctors/doctorlogin');
})
.catch(err => console.log(err));
});
});
}
});
}
});
router.post('/doctorlogin', (req,res, next) => {
passport.authenticate('local', {
successRedirect: '/doctordashboard',
failureRedirect: '/doctors/doctorlogin',
failureFlash: true
})(req, res, next);
});
router.get('/logout', (req, res) => {
req.logout();
req.flash('You are logged out');
res.redirect('/doctors/doctorlogin');
});
The two different type of users should be different through the user Schema if you are using mongoose and mongoDB as Travesty-Media uses in some of his videos, and through the permissions in different sections of your web app.
Use the same passport code that you have used for the patient user and it works. Passport takes the user info and turns it into a Bearer auth token and sends it to the client, and then when it receives it from the client it decodes it to see what kind of user is logging in...
Different users have different info but same Passport logic, even if there are 2 different patient-users. So the logic from patient to doctor regarding the Passport is the same.
If you want the patient to have access to different routes of your app, you need to insert a middleware to that route to check if the type of user is the same with what you want it to be, but after passport has got the info from the token it has received from the client side.

I'm trying to implement passport-local but i'm getting error

This is the error I'm getting in passport.js config. I don't understand what it means: Why passport.use is not a function?
TypeError: passport.use is not a function
This is my code:
const LocalStrategy = require('passport-local').Strategy;
const passport = require('passport');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// load user models
const User = require('../models/Users');
module.exports = function (passport) {
passport.use (
new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
// Match User
User.findOne({ email: email })
.then((user) => {
if (!user) {
return done(null, false, { message: 'Email is not registered' })
}
})
.catch((err) => {
console.log(err);
})
// match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw (err)
if (isMatch) {
return done(null, user)
} else {
return done(null, false, { message: 'Incorrect Password' })
}
})
})
);
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser( (id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
}
passport.js
const passport = require("passport")
const LocalStrategy = require('passport-local').Strategy;
const User = require('./models/user');
// Local Strategy
passport.use(new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {
try {
// find the user given the email
const user = await User.findOne({ "email": email });
// if not, handle it
if (!user) {
return done(null, false);
}
// check if password is correct
const isMatch = await user.isValidPassword(password);
// if not handle it
if (!isMatch) {
return done(null, false);
}
// otherwise return the user
done(null, user);
} catch (error) {
done(error, false);
}
}));

Passport error when serialize with another strategy

Create a new type of login for a different type of user (another list in the database), the login succeeds but it doesn't serialize me grow and then show it (just like it does for user). Any idea what it could be ?
Passport Config:
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
var User = require('../model/User')();
var Grow = require('../model/Grow')();
passport.use('local', new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {
// Match Email User
const user = await User.findOne({ email: email });
if (!user) {
return done(null, false, { message: 'No se encontro el usuario' });
} else {
// Match Password User
const match = await user.matchPassword(password);
if (match) {
return done(null, user);
} else {
return done(null, false, { message: 'ContraseƱa incorrecta' });
}
}
}));
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
passport.use('growlocal', new LocalStrategy({
usernameField: 'email'
}, async (email, password, done) => {
const grow = await Grow.findOne({ email: email });
if (!grow) {
return done(null, false, { message: 'No se encontro el usuario' });
} else {
const match = await grow.matchPassword(password);
if (match) {
return done(null, grow);
} else {
return done(null, false, { message: 'ContraseƱa incorrecta' });
}
}
}));
passport.serializeUser((grow, done) => {
console.log(grow)
done(null, grow.id);
});
passport.deserializeUser((id, done) => {
console.log(grow)
Grow.findById(id, (err, grow) => {
done(err, grow);
});
});
Router Config:
// Login Grow
router.get('/grows/signin', (req, res) => {
res.render('growlogin');
});
router.post('/grows/signin', passport.authenticate('growlocal', {
successRedirect: '/',
failureRedirect: '/grows/signin',
failureFlash: true
}));
EJS:
<% if (grow){ %>
Gato
<%}%>
Error:
If anyone has any idea how to fix it, please let me know. It is very important for the development of my application. Thank you very much <3

why my koa-passport authenticate parameter user is always undefined?

I'm trying to use koa-passport for koa2, and followed the examples of the author, but i always get "Unauthorized". I used the console.log and found that it even not hit the serializeUser.
var UserLogin = async (ctx, next) =>{
return passport.authenticate('local', function(err, user, info, status) {
if (user === false) {
ctx.body = { success: false }
} else {
ctx.body = { success: true }
return ctx.login(user)
}
})(ctx, next);
};
And then I searched on the web and found another writing of router, it goes to the serializeUser but the done(null, user.id) threw error that "cannot get id from undefined".
let middleware = passport.authenticate('local', async(user, info) => {
if (user === false) {
ctx.status = 401;
} else {
await ctx.login(ctx.user, function(err){
console.log("Error:\n- " + err);
})
ctx.body = { user: user }
}
});
await middleware.call(this, ctx, next)
The auth.js are showed below. Also I followed koa-passport example from the author here and tried to use session, but every request i sent will get a TypeError said "Cannot read property 'message' of undefined". But I think this is not the core problem of authentication, but for reference if that really is.
const passport = require('koa-passport')
const fetchUser = (() => {
const user = { id: 1, username: 'name', password: 'pass', isAdmin: 'false' };
return async function() {
return user
}
})()
const LocalStrategy = require('passport-local').Strategy
passport.use(new LocalStrategy(function(username, password, done) {
fetchUser()
.then(user => {
if (username === user.username && password === user.password) {
done(null, user)
} else {
done(null, false)
}
})
.catch(err => done(err))
}))
passport.serializeUser(function(user, done) {
done(null, user.id)
})
passport.deserializeUser(async function(id, done) {
try {
const user = await fetchUser();
done(null, user)
} catch(err) {
done(err)
}
})
module.exports = passport;
By the way when I use the simple default one, it will just give me a "Not found". But through console.log I can see it actually got into the loginPass.
var loginPass = async (ctx, next) =>{
passport.authenticate('local', {
successRedirect: '/myApp',
failureRedirect: '/'
});
};
In server.js:
// Sessions
const convert = require('koa-convert');
const session = require('koa-generic-session');
app.keys = ['mySecret'];
app.use(convert(session()));
// authentication
passport = require('./auth');
app.use(passport.initialize());
app.use(passport.session());
Thanks a lot for any help!!! :D

How to configure and package passport as a one module?

I test my routes in Advanced Rest Client, and with my code the output is 401, Unauthorized. I don't understand why this is happening.
I packaged my authentication in one module. Then, I invoke it in my server file with wagner-core(dependency injector):
wagner.invoke(require('./passport-init'),{ app: app })
passport.js:
'use strict'
const bCrypt = require('bcryptjs')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const session = require('express-session')
module.exports = (User, app) => {
passport.serializeUser((user, done) => {
done(null, user._id)
})
passport.deserializeUser((id, done) => {
User.findOne({ _id: id }).exec(done)
})
passport.use('login', new LocalStrategy({ passReqToCallback: true }, (req, username, password, done) => {
User.findOne({ username: username }, (err, user) => {
if (err) { return done(err) }
if (!user) { return done(null, false, { message: 'Invalid username' }) }
if (!isValidPassword(user, password)) {
return done(null, false, { message: 'Invalid password' })
}
return done(null, user)
})
}))
app.use(session({
secret: process.env.SESSION_SECRET || 'secret',
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.post('/login', passport.authenticate('login'), (req, res) => {
res.redirect('/users/' + req.user.username)
})
}
function isValidPassword (user, password) {
return bCrypt.compareSync(password, user.password)
}
I figured it out. It was something to do with my routes, and isValidpassword function.
Heres the amended code:
'use strict'
const bCrypt = require('bcryptjs')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const session = require('express-session')
module.exports = (User, app) => {
passport.serializeUser((user, done) => {
done(null, user._id)
})
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user)
})
})
passport.use('login', new LocalStrategy({ passReqToCallback: true }, (req, username, password, done) => {
process.nextTick(() => {
User.findOne({ username: username }, (err, user) => {
if (err) { return done(err) }
if (!user) { return done(null, false, { message: 'Invalid username' }) }
if (!user.password) {
bCrypt.compareSync(password, user.password)
return done(null, false, { message: 'Invalid password' })
}
return done(null, user)
})
})
}))
passport.use('signup', new LocalStrategy({ passReqToCallback: true }, (req, username, password, done) => {
process.nextTick(() => {
User.findOne({ username: username }, (err, user) => {
if (err) { return done(err) }
if (user) {
return done(null, false, { message: 'User already exists' })
} else {
let newUser = new User()
newUser.username = req.body.username
newUser.password = createHash(req.body.password)
newUser.save((err) => {
if (err) throw err
return done(null, newUser)
})
}
})
})
}))
app.use(session({
secret: 'secret',
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.get('/success', (req, res) => {
res.send({ state: 'success', user: req.user ? req.user : null })
})
app.post('/login', passport.authenticate('login', {
successRedirect: '/success',
failureRedirect: '/fail'
}))
app.post('/signup', passport.authenticate('signup', {
successRedirect: '/success',
failureRedirect: '/fail'
}))
}
function createHash (password) {
return bCrypt.hashSync(password, bCrypt.genSaltSync(10), null)
}

Resources