Using Expressjs and mongoose in a node application. I am trying to implement passportjs authentication. When I call the new LocalStrategy and passing the username and a callback function to get the username if exist, the callback function is not executing. To verify the I printed a console message is callback but even message is not showing. Why this is happening and how I can resolve it?
This is the router( index.js)
router.post('/login', (req, res, next) => {
console.log("Login POst called")
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: 'true'
})(req, res, next);
});
passport.use(new LocalStrategy(
(username, password, done)=>{
console.log("Local Strategy called")
User.getUserByUsername(username, (err, user)=>{
console.log("this message should display in callback"); // this message is not displaying
if(err) throw err;
if(!user){
return done(null, false, {message: "No user found"});
}
User.comparePassword(password, user.password, (err, isMatch)=>{
if(err) throw err;
if(isMatch){
return done(null, user);
}
else{
return done(null, false, {message: "Wrong Password"});
}
});
});
}
));
this is the model (User.js)
module.exports.getUserByUsername = (username, callback)=>{
console.log("GetUsername called")
const query = { username: username }
console.log(query);
User.findOne(query).exec(callback);
}
module.exports.getUserById = (id, callback)=>{
console.log("GetId called")
User.findId(id).exec(callback);
}
Related
I have made a user register and login but I couldnt understand why req.user shows undefined.
I couldnt understand why it shows undefined.
I have middleware of :
app.use(passport.initialize());
app.use(passport.session());
And also I have middleware of body-parser
This is my register(post):
app.post('/register',[
// username must be an email
check('kullanici_adi').notEmpty(),
// email must be at least 5 chars long
check('email').isEmail(),
// email must be at least 5 chars long
check('sifre').notEmpty(),
], async (req, res) => {
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(req.body.sifre, salt);
let kullanici = new Kullanici({
kullanici_adi: req.body.kullanici_adi,
email: req.body.email,
sifre: hashedPassword,
});
const errors = validationResult(req);
if (!errors.isEmpty()) {
req.flash('danger', 'Bütün Alanların Doldurulması Zorunludur');
res.render('kayit', {
});
}
kullanici.save(function(err) {
if (err) {
console.log(err);
} else {
res.redirect('/');
}
});
});
This is my login parts:
app.get('/login', function(req, res){
res.render('login');
});
app.post('/login', (req, res, next) => {
passport.authenticate('local', {
failureRedirect: '/login',
successRedirect: '/',
failureFlash: true,
}) (req, res, next);
});
app.get('/logout', function(req, res){
req.logout();
req.flash('success', 'You are logged out');
res.redirect('/login');
});
And this is passportjs configure part:
passport.use(new LocalStrategy({
usernameField: 'kullanici_adi',
passwordField: 'sifre'
},
function(username, password, done) {
Kullanici.findOne({ kullanici_adi: username }, function (err, kullanici) {
if (err) { return done(err); }
if (!kullanici) {
return done(null, false, { message: 'Incorrect username.' });
}
bcrypt.compare(password, kullanici.sifre, function(err, isMatch){
if(err) throw err;
if(isMatch){
return done(null, kullanici);
} else {
return done(null, false, {message: 'Wrong password'});
}
});
});
}
));
passport.serializeUser(function(kullanici, done) { done(null, kullanici.id); });
passport.deserializeUser(function(id, done) { Kullanici.findById(id, function(err, kullanici) { done(err, kullanici); }); });
When I console.log(req.kullanici) in my index or post routes then it says undefined. But at the same time this undefined user can pass through ensureAuthenticated parts of my website.
Note: Some words meaning in English:
Kullanici = User,
kullanici = user,
kullanici_adi = username,
sifre = password,
email = email,
Can someone help met? Why it is being happened and how to solve this issue?
Full code:https://github.com/michelson/dante2/issues/229
I want to do a login Form and I did nearly everything fixed but if I registered successfully and I want to log in, it throws either if the password is correct or incorrect:
UnhandledPromiseRejectionWarning: ReferenceError: err is not defined
So i looked up and the errormessage is this: bcrypt.compare(password, user.password, (err, isMatch => {
If the username is wrong or doesnt exist it just redirect me with an error message, like I programmed it.
Full controller/passport.js file
module.exports = function (passport) {
passport.use(
new LocalStrategy({ usernameField: 'username' }, (username, password, done) => {
// Matching
User.findOne({ username: username })
.then(user => {
if (!user) {
return done(null, false)
}
bcrypt.compare(password, user.password, (err, isMatch => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, flase, { message: 'Passwort nicht korrekt' })
}
}))
})
})
)
passport.serializeUser( function (user, done) {
done(null, user.id);
});
passport.deserializeUser( function (id, done) {
User.findById(id,function (err, user) {
done(err, user);
});
});
}
I include this module into my routes.js
// Login
router.get('/', forwardAuthenticated, (req, res) => {
res.render('login/index');
})
router.post('/', (req, res, next) => {
passport.authenticate('local', {
successRedirect: '../admin',
failureRedirect: '/login'
})(req, res, next)
})
app.js
require('./controller/passport')(passport);
app.use(passport.initialize());
app.use(passport.session());
I tried to remove the err but then false wouldnt be defined, I looked up the passport docu but I havnt found anything, any ideas?
I use express, passport, passport-local, mongoose
I am trying to add authentication to my express app using passport, passport-local and passport-jwt. This is what I have for the login code, I have logged the output of the generated token and I try to send it back via the response object, but when I try to login using postman, the request never finished.
passport.use('login', localStrategyLogin);
passport.serializeUser(function (user, done) {
done(null, user._id)
});
app.use(passport.initialize());
app.post('/login', (req, res, next) => {
passport.authenticate('login', {session: false}, (err, user, info) => {
if (err) {
return next(err);
}
if (!user) {
return next(new Error("Could not find user"));
}
req.login(user, {session: false}, (error) => {
if (error) return next(error);
const token = jwt.sign({_id: user._id, email: user.email}, JWT_SECRET, {expiresIn: JWT_EXPIRES});
res.send({token});
});
})(req, res, next);
});
Login Strategy:
import { Strategy as LocalStrategy } from 'passport-local';
import User from "../models/User";
export const localStrategyLogin = new LocalStrategy({usernameField: 'email', passwordField: 'password'}, async function (email, password, done) {
try {
const user = await User.findByLogin({email, password});
if (user) return done(null, user);
} catch (e) {
console.log(e.message);
}
return done(null, false, {message: 'Incorrect email or password.'});
});
The problem is you are using next instead of sending a response back.
return next(err);
Next is used to pass control to the next middleware function. If not the request will be left hanging or open.
modify it to
return res.status(500).send(err);
Whenever I try to login a user through a post request in Postman, I keep getting this error:
Here is the localStrategy I made for checking if a user's email and password can be verified:
passport.use(new LocalStrategy({usernameField: 'email', passwordField: 'password'}, function(email, password, done){
User.findOne({email: email}, (err, user) => {
if (err) return done(err);
if (!user){
return done(null, false, {message: "User is not registered"});
}
else {
const realPassword = String(user.password);
bcrypt.compare(password, realPassword, (err, result) => {
if (err) throw err;
if (result){
console.log('result is...' + result);
done(null, user)
}
else {
console.log('result is...' + result);
return done(null, false, {message: 'Invalid Password'});
}
}
});
}));
And here is the post request method in my router file:
router.post('/login', passport.authenticate('local', {session: false}), (req, res, next) => {
function generateUserToken(user){
return jwt.sign({sub: user._id, creationDate: user.creationDate}, config.secretKey);
}
if (err) throw err;
res.send({token: generateUserToken(user)})
});
UPDATE: I changed some of my code now to address issues raised. However, now instead of getting unauthorized, I keep getting a 404 not found error
In my case there where dismatch in findOne(), User schema has local.email, so I needed to search for findOne({'local.email': email}, ...).
Seems the value of doesMatch is always false.
I believe you're missing the bcrypt.compare doesn't return anything.
It is asynchronous, so, you can't get the result using the return statement.
You have to put everygint inside of the callback function from bcrypt.compare
bcrypt.compare(password, realPassword, (err, result) => {
if (err) throw err;
// NOW YOU HAVE THE VALUE FORM THE COMPARISON
if (result){
done(null, user)
}
else {
return done(null, false, {message: 'Invalid Password'});
}
});
Let me know if it works.
Hope it helps you.
#set up passport
LocalStrategy = require('passport-local').Strategy
passport.use(new LocalStrategy({usernameField: 'email'}, (email, password, done) ->
User.findOne({ email: email }, (err, user) ->
console.log("findone")
if err?
console.log "error"
return done(err)
if not user
console.log("incorrect username")
return done(null, false, { message: 'Incorrect username.' })
if password isnt user.password
console.log "NOT"
return done(null, false, {message: "Incorrect password" })
console.log "BUT YESS"
done(null,user)
)
))
passport.serializeUser((user, done) ->
done(null, user._id)
)
passport.deserializeUser((id, done) ->
User.findById(id, (err, user) ->
done(err, user)
)
)
I am using the LocalStrategy example as found at http://passportjs.org/guide/username-password/
Now, my problem is that if I enter a wrong password, or an incorrect username, I get an error Error: failed to serialize user into session.
In fact, in my serializeUser function, user is false. This probably is because the code literally returns false as the second parameter above:
return done(null, false, {message: "Incorrect password" })
But this is from the docs! So what am I doing wrong? Why do I have a serialization problem when parameters are incorrect? When parameters are ok (username and password correct), I can login without problems
EDIT: Upon comment by #robertklep here is how I use the authentication function. Indeed, because I need to route differenly depending on role, I use the passport custom method (this detail added to title of question):
app.post '/login', (req, res, next) ->
passport.authenticate('local', (err, user, info) ->
return next(err) if err?
return res.redirect('/login', { message: req.flash('Access denied')}) if not user?
req.logIn user, (err) ->
if err?
console.log "err! " + err
res.redirect("/", { message: req.flash(err)})
return
if user.role is "admin" or user.role is "auditor"
res.redirect("/dashboard")
else
res.redirect("/start")
)(req, res, next)
passport.use(new LocalStrategy( function(username, password, done) {
user.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
//check for incorrect username
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
//incorrect password for the selected username
if (user.password != password) {
return done(null, false, { message: 'Invalid password' });
}
return done(null, user);
});
}
));
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user,info) {
if (err) {
//console.log(info);
return next(err); }
if (!user) {
console.log(info);
return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err);
}
return res.redirect('https://www.google.co.in' );
});
})(req, res, next);
});
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(login, done) {
user.findById(login._id, function(err, user) {
done(err, user);
});
});
app.post '/login', (req, res, next) ->
passport.authenticate('local', (err, user, info) ->
console.log "authenticate callback"
if err?
console.log "err in authenticate callback"
return next(err)
if not user
console.log "User NOT in auth callback"
req.flash("Accesso no otorgado", info.message)
return res.redirect('/login')
I rewrote a bit the authenticate function.
Instead of if not user?, the solution is to use if not user (no question mark!), as the "user" returned is just a boolean set to false when things went wrong.