Passport local returns error 400 bad request with postman - passport.js

Hi i am getting 400 Bad Request error every time i use passport local. Please tell me where i am doing something wrong.
I am trying to call my /login route using postman but every time i am getting error of 400 Bad Request
Below is my code:
passport.use(new LocalStrategy(
{
email:'email',
password:'password'
},
function(email, password, done){
adminModel.getAdmin(email, function(err, admin){
if(err){ return done(err);}
if(!admin){
return done(null, false, {message: 'Invalid Username.'});
}
adminModel.comparePassword(password, admin.password, function(err, isMatch){
if(err){return done(err);}
if(isMatch){
return done(null, admin);
}else{
return done(null, false, {message: 'Invalid Password'});
}
})
});
}
));
passport.serializeUser(function(admin, done){
done(null, admin._id);
});
passport.deserializeUser(function(id, done){
adminModel.findById(id,function(err, admin){
done(err, admin);
});
});
router.post('/login', passport.authenticate('local'),function(req, res){
res.send(req.body);
});

From what you've given its impossible to say for sure, but I would say nine out of ten times HTTP Bad Request comes from this row in passport-local, ie. the request does not contain credentials.
Apparently you have tried to tell that the fields containing the credentials are email and password when you've defined this:
{
email:'email',
password:'password'
}
These options are not supported by the middleware. You should pass
{
usernameField: 'email',
passwordField: 'password'
}
instead.
Another common reason is to not have body-parser in use, or the request you're sending from Postman does not define correct headers to match the data.

Related

Understanding done function in PassportJS

I am trying to implement a normal login and signup module and I am facing difficulty in understanding the done function.here is the line I feel is responsible for the done function. Now what I wanted to do was return the corresponding messages like if there was some server error.
app.post('/user/auth/login', passport.authenticate('local-login'), function(req, res) {
console.log("Login Request Successful");
if(req.user){
res.status(200).send(JSON.stringify({
'msg' : "Successfully logged in"
}));
}
else{
res.status(400)
}
//console.log(req.user);
});
This is for the case when after logging in Passport attaches a user object to the request module.
But how do I differentiate between a server error and authentication failed error
Here is my authenticate middleware.
passport.use('local-login', new LocalStrategy({
passReqToCallback: true
}, function(req, username, password, done) {
Users.findOne({
'emailId': username
}, function(err, user) {
if (err)
return done(err);
if (!user)
return done(null, false);
else if (passwordHash.verify(password, user.password)) {
console.log("User is verified");
req.session.save();
return done(null, user);
} else
return done(null, false);
});
}));
Basically, I need to access the messages in done() function. How do I do that?
How does function, like if I type the wrong password, the message I get in my browser in Unauthorized. It means somewhere it is setting the response.data field to Unauthorized. Instead of that I want to know when there is an error and want to send my custom message.
I don't know what do you mean by
access the messages in done() function
, however You can very well do with supplying addition object with message in done callback
if (!user) {
return done(null, false, {
message: 'Unknown user or invalid password'
});
}
if (!user.authenticate(password)) {
return done(null, false, {
message: 'Unknown user or invalid password'
});
}
Another method.
I don't know how I missed it. There is an option of custom callbacks in the docs. Here is the implementation of the same.
app.post('/user/auth/login', function(req, res) {
passport.authenticate('local-login', function(err, user, info) {
if (err) {
res.status(500).send(JSON.stringify({
'msg': "Internal Server Error"
}));
}
if (!user) {
res.status(401).send(JSON.stringify({
'msg': "Username or Password is incorrect"
}));
}
if (user) {
res.status(200).send(JSON.stringify({
'msg': "Successfully logged in"
}));
}
})(req, res, next);
});
The only issue with this solution is that you will have to manually login and create session and all that.
An optional callback can be supplied to allow the application to overrride the default manner in which authentication attempts are
handled. The callback has the following signature, where user
will be set to the authenticated user on a successful
authentication attempt, or false otherwise. An optional info
argument will be passed, containing additional details provided by
the strategy's verify callback.
app.get('/protected', function(req, res, next) {
passport.authenticate ('local',function(err, user, info) {
if (err) { return next(err) }
if (!user) { return res.redirect('/signin') }
res. redirect('/account');
})(req, res, next);
});
Note that if a callback is supplied, it becomes the application's responsibility to log-in the user, establish a session, and otherwise
perform the desired operations.

express is unable to authenticate

I have been following mean stack videos done by microsoft visual academy(mva). I have been struck at module 3 of MVA. When I enter a username and password, it always redirects to failure route.
passport.js:
passport.use('signup', new LocalStrategy({
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, username, password, done) {
if (users[username]){
console.log('User already exists with username: ' + username);
return done(null, false);
}
//store user in memory
users[username] = {
username: username,
password: createHash(password)
}
console.log(users[username].username + ' Registration successful');
return done(null, users[username]);
})
);
authenticate.js:
router.get('/success', function(req, res){
res.send({state: 'success', user: req.user ? req.user : null});
});
//sends failure login state back to angular
router.get('/failure', function(req, res){
res.send({state: 'failure', user: null, message: "Invalid username or password"});
});
//log in
router.post('/login', passport.authenticate('login', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failure'
}));
I actually followed steps given in https://github.com/hwz/chirp/tree/master/module-3
Any help is appreciated. Thanks in advance :)
I think you should try changing Content-Type to application/x-www-form-urlencoded.
Ok, so I've got solution for you. Don't send data in headers but via payload. Yes, it's simple as it.
By the way I recommend you to check in passport.js login method. There is typo in their Github respository. They've forget ! symbol in
if(users[username]){
console.log('User Not Found with username '+username);
return done(null, false);
}
so it should be:
if(!users[username]){
console.log('User Not Found with username '+username);
return done(null, false);
}

Node.js passport pass postdata on to failureRedirect

This is driving me crazy!
I'm using Express 4, passport and local-passport to authenticate login and signup.
I'm using this example:
https://github.com/tutsplus/passport-mongo
Problem:
When the signup form does not validate (say you forgot one of the fields) and we redirect to the failureRedirect (which is the same signup page), all the entered values are gone. Not a very good user experience that you have to fill out the entire form because you messed up a single field.
How do I pass the already entered data on the the form?
I got these two routes handing the GET and POST of the form:
app.get('/signup', function(req, res){
res.render('signup', {
message: req.flash('message'),
});
});
app.post('/signup', passport.authenticate('signup', {
successRedirect: '/signup-complete',
failureRedirect: '/signup', // need to pass the entered values (if any) back to the signup page
failureFlash : true
}));
I have a nagging suspicion that the values are already there - I just don't know how to grab them.
I'm using Swig for the views btw.
Did you add connect-flash middleware to your app?
var flash = require('connect-flash');
app.use(flash());
Update:
When you define your local strategy, you should return the flash messages in the third parameter of the done function. Example:
passport.use(new LocalStrategy(
function(username, password, done) {
findByUsername(username, function(err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false, { message: 'Unknown user ' + username }); }
if (user.password != password) { return done(null, false, { message: 'Invalid password' }); }
return done(null, user);
})
});
}
));

passport-local with node-jwt-simple

How can I combine passport-local to return a JWT token on successful authentication?
I want to use node-jwt-simple and looking at passport.js I am not sure how to go about.
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
Is it possible to return the token when calling done() ?
Something like this... (just pseudo code)
if(User.validCredentials(username, password)) {
var token = jwt.encode({username: username}, tokenSecret);
done(null, {token : token}); //is this possible?
}
If not, how can I return the token?
I figured it out!
First of all you need to implement the correct strategy. In my case LocalStrategy, and you need to provide your validation logic. For example sake let's use the one in passport-local.
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
the verify call back you provide function(username, password, done) will take care of finding your user and checking if the password matches (beyond the scope of the question and my answer)
passport.js expects several pieces for it to work, one is that you return the user in the strategy. I was trying to change that part of the code, and that was wrong. The callback expects false if the validation fails and an object (the validated user) if you are successful.
Now.... how to integrate JWT?
In your login route you will have to handle a successful auth or an unsuccessful one. And it is here that you need to add the JWT token creation. Like so:
(remember to disable the session, otherwise you will have to implement the serialize and deserialize functions. And you don't need those if you are not persisting the session, which you are not if you are using a token based auth)
From passport-local examples: (with the JWT token added)
// POST /login
// This is an alternative implementation that uses a custom callback to
// achieve the same functionality.
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err) }
if (!user) {
return res.json(401, { error: 'message' });
}
//user has authenticated correctly thus we create a JWT token
var token = jwt.encode({ username: 'somedata'}, tokenSecret);
res.json({ token : token });
})(req, res, next);
});
And that is it! Now when you call /login and POST username and password (which should always be over SSL) the first code snippet above will try to find a user based on the username you provided and then check that the password matches (Of course you will need to change that to suit your needs).
After that your login route will be called and there you can take care of returning an error or a valid token.
Hope this will help someone. And if I have made any mistakes or forgot something let me know.
This is a great solution, I just want to add this:
var expressJwt = require('express-jwt');
app.use('/api', expressJwt({secret: secret}));
I like to use "express-jwt" to validate the token.
btw: this article is great to learn how to handle the token in the client side, using Angular, in order to send it back with every request
https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
Here's a boiler-plate I'm working on for specifically using api tokens only (no sessions...not that session are bad of course; just we're using token approach):
https://github.com/roblevintennis/passport-api-tokens

Unable to get passport/express to work with LocalStrategy. Get 401

I thought I followed the documentation, yet I'm get a 401 response.
I have a simple POST form that receives the 401 response.
This is my sample code (CASE 1):
passport.serializeUser(function(user, done) {
console.log("Serializing:", user);
done(null, JSON.parse(user));
});
passport.deserializeUser(function(obj, done) {
console.log("Deserializing:" + obj);
done(null, obj);
});
passport.use(new LocalStrategy(
function(username, password, done) {
console.log("Authenticating.....:" + username);
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
app.post('/auth/login',
passport.authenticate('local'),
function (req, res) {
console.log("Made it here");
}
);
The above code never prints any of the messages sent to the console.log. All I see is a message from nodejs/express showing the "POST /auth/login 401" in the console.
The interesting thing is that I changed the app.post function as follows (CASE 2):
app.post('/auth/login',
passport.authenticate('local', {
successRedirect:'/partials/playlist/playlists',
failureRedirect:'/partials/welcome'
}),
function (req, res) {
console.log("Made it here");
}
);
This time around the only link that gets invoked is the /partials/welcome' redirect as "POST /auth/login 302". Again, no messages logged in the console.
My questions:
Why the different behavior of the two app.post implementations (CASE 1 vs CASE 2)?
Why is my "SucessRedirect" never called in CASE 2?
Why nothing gets printed in the the console.log?
Any ideas?

Resources