Passport ReferenceError: err is not defined - node.js

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

Related

How do i test postman when i have passport authentication

Im trying to test using postman but i have a passport authentication which is blocking me from testing as it will redirect me to the login screen it is not authenticated.
How i can get a token or authenticate myself in postman to be able to test
I have tried to use /auth/local in postman but it just returns that i cant get the route
Passport.js
var LocalStrategy = require('passport-local').Strategy;
var { User } = require('../model/user.js');
var bcrypt = require('bcrypt');
module.exports = function (passport) {
passport.use(new LocalStrategy(function (username, password, done) {
let query = { username: username };
User.findOne(query, function (err, user) {
if (err) throw err;
if (!user) {
return done(null, false,{ message: 'No user found' });
}
bcrypt.compare(password, user.password, function (err, isMatch) {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false,{ message: 'Wrong password' });
}
});
});
}));
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
}
Route.js
router.get('/register', function (req, res) {
res.sendFile(__dirname + "/views/register.html");
});
router.post('/register', async (req, res) => {
var data = req.body;
var salt = await bcrypt.genSalt(10)
var hashedpw = await bcrypt.hash(data.password, salt)
const newUser = await User.create({
name: data.name,
email: data.email,
username: data.username,
password: hashedpw,
});
newUser.save();
req.flash('success', 'You are now registered and can log in');
res.redirect('/');
});
router.get('/login', function (req, res) {
res.locals.success = req.flash('success');
res.locals.error = req.flash('message');
res.render(__dirname + "/views/login.ejs");
});
router.post('/login', async (req, res, next) => {
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true
})(req, res, next);
});
router.get('/logout', async (req, res) => {
req.logout(function (err) {
if (err) { return next(err); }
req.flash('success', 'You are logged out');
res.redirect("/")
});
});
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
res.redirect('/login');
}
}
Following this guide:
https://mevelix.com/articles/postman-auth-for-laravel,4
you have to create the Command:
php artisan make:command DevPostman
then in the newly created class, copy the content it is showed in the link,
inside the class namespace App\Console\Commands\DevPostmanCommand
Then you can execute the command:
php artisan dev:postman web
in this way you are creating a simulated session.
This is my ouput, for example:
you paste this output directly in PostMan, inside the Tab Pre-Request Scripts:
In this way you are allowed to avoid the login inside Postman, because you are simulating a session.
See the first link to have the complete code of the DevPostmanCommand class.

Identifyng Error: Cannot set headers after they are sent to the client on my passportJS app

I'm getting that error, and besides asking where it is on my code I would like to know if there is a better way to log errors in order to get to know where it is being generated on my code, since I can't figure it out by reading the error log. Here are the code and the error. Thanks! StackOF is making me add more details, I don't know what to write
/////// app.js
//Function one : setting up the LocalStrategy
passport.use(
new LocalStrategy((username, password, done) => {
User.findOne({ username: username }, (err, user) => {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, { message: "Incorrect username" });
}
if (bcrypt.compare(password, user.password, (err, res) => {
if (res) {
// passwords match! log user in
return done(null, user)
} else {
// passwords do not match!
return done(null, false, { message: "Incorrect password" })
}
})) {
return done(null, false, { message: "Incorrect password" });
}
return done(null, user);
});
})
);
//Functions two and three: Sessions and serialization
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
//Route for logging in
app.post(
"/log-in",
passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/"
})
);
app.use(function(req, res, next) {
res.locals.currentUser = req.user;
next();
});
app.get("/", (req, res) => {
res.render("index", { user: req.user });
});
app.get("/sign-up", (req, res) => res.render("sign-up-form"));
app.post("/sign-up", (req, res, next) => {
bcrypt.hash(req.body.password, 10, (err, hashedPassword) => {
// if err, do something
if (err) {
return next(err);
}
// otherwise, store hashedPassword in DB
// eslint-disable-next-line no-unused-vars
const user = new User({
username: req.body.username,
password: hashedPassword
}).save(err => {
if (err) {
return next(err);
}
return res.redirect("/");
});
});
});
app.get("/log-out", (req, res) => {
req.logout();
res.redirect("/");
});
app.listen(3000, () => console.log("app listening on port 3000!"));
And the error:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:558:11)
at ServerResponse.header (C:\Users\Atom\Desktop\passportJSOdin\node_modules\express\lib\response.js:771:10)
at ServerResponse.location (C:\Users\Atom\Desktop\passportJSOdin\node_modules\express\lib\response.js:888:15)
at ServerResponse.redirect (C:\Users\Atom\Desktop\passportJSOdin\node_modules\express\lib\response.js:926:18)
at complete (C:\Users\Atom\Desktop\passportJSOdin\node_modules\passport\lib\middleware\authenticate.js:266:26)
at C:\Users\Atom\Desktop\passportJSOdin\node_modules\passport\lib\middleware\authenticate.js:275:15
at pass (C:\Users\Atom\Desktop\passportJSOdin\node_modules\passport\lib\authenticator.js:431:14)
at Authenticator.transformAuthInfo (C:\Users\Atom\Desktop\passportJSOdin\node_modules\passport\lib\authenticator.js:453:5)
at C:\Users\Atom\Desktop\passportJSOdin\node_modules\passport\lib\middleware\authenticate.js:272:22
at C:\Users\Atom\Desktop\passportJSOdin\node_modules\passport\lib\http\request.js:52:7
at C:\Users\Atom\Desktop\passportJSOdin\node_modules\passport\lib\sessionmanager.js:26:5
at pass (C:\Users\Atom\Desktop\passportJSOdin\node_modules\passport\lib\authenticator.js:277:43)
at serialized (C:\Users\Atom\Desktop\passportJSOdin\node_modules\passport\lib\authenticator.js:286:7)
at C:\Users\Atom\Desktop\passportJSOdin\app.js:63:5
at pass (C:\Users\Atom\Desktop\passportJSOdin\node_modules\passport\lib\authenticator.js:294:9)
at Authenticator.serializeUser (C:\Users\Atom\Desktop\passportJSOdin\node_modules\passport\lib\authenticator.js:299:5)
There is a glaring issue in the logic of your code here:
if (bcrypt.compare(password, user.password, (err, res) => {
if (res) {
return done(null, user)
} else {
return done(null, false, { message: "Incorrect password" })
}
})) {
return done(null, false, { message: "Incorrect password" });
}
return done(null, user);
bcrypt.compare() is an asynchronous function, which means it does not return the result it produces to its calling code, but instead passes it to its callback function once available. So the continuation of the code - ie everything that should happen once the result is available - should be wrapped in its callback function.
You got this right. But then you are duplicating the logic of what happens in this callback function in the calling code based on the returned value of bcrypt.compare() - which is irrelevant.
The end result is that the done() function will end up being called twice.
You should just do:
bcrypt.compare(password, user.password, (err, res) => {
if (res) {
return done(null, user)
} else {
return done(null, false, { message: "Incorrect password" })
}
})
As far as logging errors, a stack trace is as good as it gets to help pinpoint the issue.

After Login req.user is Undefined(Passportjs + Nodejs)

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

passport login with JWT

I'm trying to implement login endpoint with passport.js. My user schema contains nickname and password. So far in app.js I have:
require('./config/passport');
app.use('/user', passport.authenticate('jwt', {session: false}), require('./routes/user/login.js'));
I require my file passport.js which have passport strategy configuration:
passport.use(new LocalStrategy({ usernameField: 'nickname' }, (nickname, password, done) => {
User.findOne({ nickname: nickname })
.then(user => {
if(!user) {
return done(null, false, { message: 'Email and/or password is not valid' });
}
bcrypt.compare(password, user.password, (err, isMatch) => {
if(err) throw err;
if(isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Email and/or password is not valid' });
}
});
});
})
);
passport.use(new JWTStrategy({
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
secretOrKey: keys.secretJWT
},
function (jwtPayload, cb) {
return User.findOneById(jwtPayload.id)
.then(user => {
return cb(null, user);
})
.catch(err => {
return cb(err);
});
})
);
and in app.js (first snippet) on /user I'm requirung actual endpoint which is:
router.post('/login', function (req, res, next) {
passport.authenticate('local', {session: false}, (err, user, info) => {
console.log(info);
if (err || !user) {
return res.status(400).json({
message: 'Email and/or password is not valid',
user: user
});
}
req.login(user, {session: false}, (err) => {
if (err) next(err);
//generate a signed JWT with the contents of user object and return it in the response
const token = jwt.sign(user, keys.secretJWT);
return res.json({user, token});
});
})(req, res);
});
so in the end it is invoked when calling /user/login. Weird to me is that console.log(info); never actually consoles, I can't see it in terminal in which my node app is running.
I'm passing valid nickname and password but I always get 401 Unauthorized:
What am I missing? Maybe it's because I'm not passing token? But on login I don't know the token. It should be in response of login. And then I will authenticate with token on further requests.
I think you are missing your strategy alias in passport.use() function. You use a alias jwt in your router:
passport.authenticate('jwt', {session: false})
So your passport.use() function should look like this:
passport.use('local', new LocalStrategy(...), function(payload, cb){...})
passport.use('jwt', new JWTStrategy(...), function(payload, cb){...})
Otherwise you cant match a proper strategy with an alias. Also in a login controller you have to call passport with a 'local' alias in this case.

Why Callback not working with mongoose findOne method?

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);
}

Resources