I'm using Passport.js for authentication in my node/express app, when input fields are empty passport displays default message "Missing credentials", how can i change that? to say something like please fill the form or something
here my local strategy for login:
passport.use('login', new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function(email, password, done) {
models.User.findOne({where: {email}}).then(user => {
if (!user)
return done(null, false, {message: 'Email not registered'});
user.checkPassword(password).then(res => {
if (!res)
return done(null, false, {message: 'Incorrect username or password'});
return done(null, user);
});
});
}));
login route:
router.post('/login', passport.authenticate('login', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true
}));
I got it, looks like i can pass optional callback to authenticate function to override default functionality, thanks oneturkmen for reference.
here's modified route:
router.post('/signup', (req, res) => {
passport.authenticate('signup', (err, user, info) => {
const body = req.body;
if (req.body.username === '' || req.body.email === '' || req.body.password === '')
info.message = 'Please fill the form';
req.logIn(user, err => {
if (err) res.render('users/signup', info);
else res.redirect('/');
});
})(req, res);
});
An alternative is to add "badRequestMessage" to your code
Your code will look like this
router.post('/login', passport.authenticate('login', {
successRedirect: '/',
failureRedirect: '/login',
badRequestMessage : 'Please fill the form',
failureFlash: true
}));
Related
app.post('/login', checkNotAuthenticated, passport.authenticate('local', {
failureFlash: true
});
I am trying to find a way that when I do a POST request to /login, to get back a JSON like this without any kind of redirect:
{"success": true/false, "message": "Message of what went wrong, e.g.: Password incorrect"}
The passport code:
function initialize(passport, getUserByEmail, getUserById) {
const authenticateUser = async (email, password, done) => {
const user = getUserByEmail(email);
if (user == null) {
return done(null, false, {message: 'No user with that email'});
}
try {
if (await bcrypt.compare(password, user.password)) {
return done(null, user);
} else {
return done(null, false, {message: 'Password incorrect'});
}
} catch (e) {
return done(e);
}
};
passport.use(new LocalStrategy({
usernameField: 'email'
}, authenticateUser));
passport.serializeUser((user, done) => done(null, user.id));
passport.deserializeUser((id, done) => {
return done(null, getUserById(id))
});
}
The login works fine, I just don't know how to send that response, as I am not able to send anything inside the passport function. I tried adding a new function like this:
app.post('/login', checkNotAuthenticated, passport.authenticate('local', {
failureFlash: true
}, (req, res, msg) => {
console.log(req);
console.log(res);
console.log(msg);
}));
But this function is what I send in the previous passport function through "done". So I can get the message from there to send, but I don't have the same "res" containing the res.send method.
I'm trying to build an authentication system with passport-local. I got the initial starter code from here: https://www.digitalocean.com/community/tutorials/easy-node-authentication-setup-and-local#toc-handling-signupregistration
When I try console.log(req.user), it gets logged successfully, meaning that passport does return req.user.
However, when redirecting to the logged-in route, req.user becomes undefined. How can I get req.user to be sent to my logged-in route?
Here is my code.
Frontend request:
const serverResponse = fetch('http://localhost:5000/api/client/signin', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(x)
})
.then((res)=> {
if (res.user) {
alert('Sign in successful.')
return res.user
} else {
alert('Try again.')
}})
.catch((err)=> {
alert(`Error: ${err}`)
})
Backend sign-in route:
router.post('/signin', passport.authenticate('local-login', {
successRedirect: '/api/client/profile',
failureRedirect: '/api/client/signin',
failureFlash: true
}))
Passport js login config file:
passport.use('local-login', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
// find a user whose email is the same as the forms email
UserModel.findOne({
email: req.body.email
}, function(err,
user) {
// if there are any errors,
if (err)
return done(err);
// if no user is found,
if (!user) {
console.log('That account does not exist!')
return done(null, false, req.flash('loginMessage', 'No user found.'));
}
// if the password is wrong
if (user.password != password) {
console.log('Wrong password!')
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
}
// all is well, return successful user
return done(null, user);
});
}));
Logged-in check
function loggedIn(req, res, next) {
if (req.user) {
console.log(`User: found.`)
return next();
} else {
console.log('No user object.')
}
}
Finally, logged-in route
router.get('/profile', loggedIn, (req, res) => {
console.log('User logged in.')
console.log(`${req.user}`)
res.send(req.user)
})
Please, I'm trying to redirect to the "edit user route" page after login but the req.user._id is showing undefined, any idea what's wrong here?
login router
router.post('/login', (req, res, next) => {
passport.authenticate('local', {
successRedirect:'../profiles/edit/' + req.user._id, <<<< **UNDEFINED**
failureRedirect:'./login',
failureFlash: true,
})(req, res, next);
});
passport.js
module.exports = function(passport) {
passport.use(new LocalStrategy({
},
(username, password, done) => {
Profile.findOne({
username:username
}).then(user => {
if(!user) {
return done(null, false, {message: 'No user found'});
}
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, {message: 'Password Incorrect'});
}
})
})
}
));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
Profile.findById(id, function(err, user) {
done(err, user);
});
});
}
app.js
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true,
}));
app.use(passport.initialize());
app.use(passport.session());
I'm getting:
TypeError: Cannot read property '_id' of undefined
You can't get user details in the authenticate method, it will check if username has been found and then pass it to the next middleware
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login' }),
function(req, res) {
// here you can access user info
res.redirect('../profiles/edit/' + req.user._id);
});
I am using passport local for authenticating the application .I understood to perform login
Now i wanted to implement registration for the same
I understood we can provide a name to distinguish both local strategy
but i don't know how to invoke them
Login:
app.post('/login',
passport.authenticate('local', {
successRedirect: '/loginSuccess',
failureRedirect: '/loginFailure',
failureFlash: true
}));
passport.use('login',new LocalStrategy(
function(username, password, done) {
process.nextTick(function () {
});
UserDetails.findOne({'username':username},
function(err, user) {
if (!user) { return done(null, false , { message: 'Incorrect username.' }); }
if (err) { return done(err); }
if (user.password != password) { return done(null, false , { message: 'Incorrect password.' }); }
return done(null, user);
});
}
));
app.post('/register',
passport.authenticate('local', {
successRedirect: '/loginSuccess',
failureRedirect: '/loginFailure',
failureFlash: true
}));
passport.use('register',new LocalStrategy(
function(username, password, done) {
process.nextTick(function () {
});
UserDetails.findOne({'username':username},
function(err, user) {
if (user) { return done(null, false , { message: 'EmailId Already exits' }); }
if (err) { return done(err); }
return done(null, user);
});
}
));
where should i configure login and register to pick up corresponding strategy accordingly i am a new bee please revert if someone not understood my question
Updating as cant put code in comment:
Please go through with this article https://scotch.io/tutorials/easy-node-authentication-setup-and-local
and let us know if you face any issue.
You can define it in your end points ..see below.. here /login is your end point where you will receive your requests and in function do your coding for checking user, etc and send res.json with response to user.
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
});
So I am trying to add local authentication to my MEAN stack app.
Everything was running smoothly. Sign up works great. But I cannot log in as a user.
I am getting:
POST /login 302 3.979 ms - 58
on the console (via Morgan)
But there is certainly an error (express routes to the "failureRedirect" set via passport)
Could it be a problem reading from the db? Why would I be able to write to it then...
A test with chai reveals that the program cannot "find user by email" from the db via User Model
anyone have any clue why this is happening?
Here is my passport strategy code:
/config/passport.js
var LocalStrategy = require('passport-local').Strategy;
var User = require('../models/users');
module.exports = function(passport) {
// passport session setup ==================================================
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
// local login =============================================================
passport.use('local-login', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done) {
User.findOne({ 'local.email' : email }, function(err, user) {
if (err)
return done(err);
if (!user)
return done(null, false, req.flash('loginMessage', 'No user found.'));
if (!user.validPassword(password))
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
return done(null, user);
});
}));
// local sign up =============================================================
passport.use('local-signup', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true
},
function(req, email, password, done) {
User.findOne({ 'local.email' : email }, function(err, user) {
if (err)
return done(err);
if (user) {
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
} else {
var newUser = new User();
newUser.local.email = email;
newUser.local.password = newUser.generateHash(password); // use the generateHash function in our user model
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
}));
};
Here's the routes:
// /login ======================================================================
app.route('/login')
.get(function(req, res) {
res.setHeader('Content-Type', 'text/html');
res.render('login.html');
})
.post(passport.authenticate('local-login', {
successRedirect : '/profile',
failureRedirect : '/'
}));
// /signup ======================================================================
app.route('/signup')
.get(function(req, res) {
res.setHeader('Content-Type', 'text/html');
res.render('signup.html');
})
.post(passport.authenticate('local-signup', {
successRedirect : '/profile',
failureRedirect : '/'
}));
Login Strategy
// passport/login.js
passport.use('login', new LocalStrategy({
passReqToCallback : true
},
function(req, username, password, done) {
// check in mongo if a user with username exists or not
User.findOne({ 'username' : username },
function(err, user) {
// In case of any error, return using the done method
if (err)
return done(err);
// Username does not exist, log error & redirect back
if (!user){
console.log('User Not Found with username '+username);
return done(null, false,
req.flash('message', 'User Not found.'));
}
// User exists but wrong password, log the error
if (!isValidPassword(user, password)){
console.log('Invalid Password');
return done(null, false,
req.flash('message', 'Invalid Password'));
}
// User and password both match, return user from
// done method which will be treated like success
return done(null, user);
}
);
}));
We now define our routes for the application in the following module which takes the instance of Passport created in app.js above. Save this module in
module.exports = function(passport){
/* GET login page. */
router.get('/', function(req, res) {
// Display the Login page with any flash message, if any
res.render('index', { message: req.flash('message') });
});
/* Handle Login POST */
router.post('/login', passport.authenticate('login', {
successRedirect: '/home',
failureRedirect: '/',
failureFlash : true
}));
/* GET Registration Page */
router.get('/signup', function(req, res){
res.render('register',{message: req.flash('message')});
});
/* Handle Registration POST */
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/home',
failureRedirect: '/signup',
failureFlash : true
}));
return router;
}