How is the verify callback used in the API? - node.js

While going through the API documentation of passport-local, it is mentioned that the strategy requires a verify callback.
Below is the example that is provided.
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); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
Here, .verifyPassword(password) is used as a callback?
Link for API is this.
And If I want to give email instead of username then how should I approach this?

1) user.verifyPassword(password) - synchronous function.
2) By default, LocalStrategy expects to find credentials in parameters named
username and password. If your site prefers to name these fields differently,
options are available to change the defaults:
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'passwd'
},
function(username, password, done) {
// ...
}
));

Related

PassportJS Node: why need serializeUser and deserializeUser even when not using session?

exports.initPassportLocalStrategy = function () {
passport.use(new LocalStrategy(
{
session: false
},
function(username, password, done) {
UserProxy.validateUserWithPassword(username, password)
.then(function (user) {
if(user) done(null, user);
else done(null, false);
})
.catch(done);
}
));
passport.serializeUser(function(user, cb) {
cb(null, user);
});
};
I'm implementing a token based auth middleware without seesion. So I was wondering why do I need to provide a serialzeUser function? I have read that the reason is to put user or some of its properties into the session and then desearlizeUser would retrieve the whole object from the session and put it in the req.user .
So here are my questions:
Why can't the done(null, user); in the LocalStrategy function put the user into req.user ? Why even bother serialise and deserailie?
If remove the searlizeUser function I will get an error, but I can get away without a deserilzeUser function, why? And in this case, who puts the user object to req.user?
Many thanks.
You don't need serialize/deserialize. Your setup is slightly wrong.
You need to move the session: false out of the strategy and into passport.authenticate. This is because strategies can't decide this, it's rather dependent on your route which kind of authentication you want.
passport.use(new LocalStrategy(
function(username, password, done) {
UserProxy.validateUserWithPassword(username, password)
.then(function (user) {
if(user) done(null, user);
else done(null, false);
})
.catch(done);
}
));
app.use(passport.initialize());
app.post('/auth', passport.authenticate(
'local', {
session: false // here goes the session false
}), doWhateverYourSetupNeeds);

Passport-local 304 redirect error express app

I am being throw a redirect error and I can't seem to work out why, I've gone through the docs with a fine-toothed comb and nothing seems wrong. On submitting my forms (both login and register) I receive a 304.
login
router.get('/login', function(req, res, next) {
res.render('login', {
user: req.user
})
})
Template
extends layout
block content
.container
h1 Login
br
form(method="post", action="/login", class="form")
.form-group
input.form-control(type='text', name='email', required='required')
.form-group
input.form-control(type='password', name='password', required='required')
button.btn.btn-default(type='submit') submit
a(href='/')
button.btn.btn-default(type='button') Go back
Passport config
// Configure passport
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function(username, password, done) {
UserSchema.authenticate()
}
));
//passport.use(new LocalStrategy(UserSchema.authenticate()))
passport.serializeUser(UserSchema.serializeUser())
passport.deserializeUser(UserSchema.deserializeUser())
Where am I going wrong?
I believe that your callback function in the passport.use() function needs to return in a fashion as below (this is taken from a working implementation from one of my projects). You can see that the done() callback passed into the function is called like done(null, false) when authentication was unsuccessful, and done(null, user) when authentication is successful (I am passing the user variable here for usage elsewhere).
function(username, password, done) {
//check if user is authenticated, in my case the user variable
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.authenticate(password)) { return done(null, false); }
if (!user.active) { return done(null, false); }
return done(null, user);
}

Passport.js positive result

I am attempting to authenticate a user in a Node app using Sequelize and Passport. I am able to hit my database but can't seem to get a positive result. Basically, I have a simple frontend form that accepts a username and password (using the respective names "username" and "password") and then the following Passport definition:
passport.use(new localStrategy(
{usernameField: 'email'},
function(req, email, password, done) {
models.TeacherX.findOne({ email: email }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
Then I call it with:
router.post('/login',
passport.authenticate('local', { failureRedirect: '/login?msg=failure'}),
function(req, res) {
res.redirect("/?msg=positive");
});
Since you are passing the request to the verify callback, you need to set the property passReqToCallback to true or remove the req param from the verify callback. Try this:
passport.use(new localStrategy(
{passReqToCallback: true ,
usernameField: 'email'},
function(req, email, password, done) {
models.TeacherX.findOne({ email: email }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));

How can i switch to another user account from an admin account

I have a user table in which i have an Admin account and some other normal users accounts.
I want to do all activities which for a particular user. It should act like that activity done by same user.
Can somebody tell me how can i switch to another account from Admin account
without login to that account.
Currently i use passport authentication.(passport-local)
Here is my code
app.get('/secure/group/login', function(req,res,next) {
passport.authenticate('local',function(err,user,info) {
console.log("error is "+err);
req.logIn('tessAccount',function(err) {
console.log("Weer" +err);
});
console.log("dd");
})(req,res,next);
});
});
and passport code
var LocalStrategy = require('passport-local').Strategy;
module.exports = function(passport) {
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
done(null, user.token);
});
passport.use(new BearerStrategy(
function(token, done) {
user.tokenExist(token, function(err, user) {
if (err) {
return done(err);
}
else {
return done(null, user, { scope: 'all' });
}
});
}
));
// used to deserialize the user
passport.deserializeUser(function(accessToken, done) {
user.getUserByAccessToken(accessToken, function(err, dbUser) {
if (err) {
done(err);
} else {
done(null, dbUser[0]);
}
});
});
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use('local-signup', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
user.emailExists(email, function(err, exists) {
if (err)
return done(err);
else if (exists) {
return done(null, false, {
message: req.flash('loginMessage')
});
} else {
req.userDetails.status = 0;
req.userDetails.token = md5.digest_s(req.userDetails.email + new Date());
req.userDetails.userImage = config.user.image;
user.register(req.userDetails, function(err, newUser) {
if (err)
return done(err);
else {
/*Get user Shared article if exist start*/
getSharedArticlesOfnewlyuserIfExist(email, newUser.insertId);
/*Get user Shared article if exist end*/
req.userDetails.id = newUser.insertId;
return done(err, req.userDetails);
}
});
}
});
}));
passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
// callback with email and password from our form
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
user.matchPassword({
email: email,
password: password
}, function(err, newUser) {
// if there are any errors, return the error before anything else
if (err)
return done(err);
// if no user is found, return the message
if (newUser.length > 0) {
var user = {
id: newUser[0].user_id,
email: newUser[0].email_id,
token: newUser[0].user_access_token
};
return done(null, user);
} else {
return done(null, false, {
message: 'Incorrect username or password.'
}); // req.flash is the way to set flashdata using connect-flash
}
});
}));
User.findOne({ username: 'Myusername' }, function(err, user) {
req.logIn(user, function(err){});
});
This worked for me to log into an account without using password, it switches from my admin account to an user account.
Actually I'm using passport.js and mongoose

Passport-facebook access req object from within callback function

On the callback from Facebook for nodejs passport authentication, how do you get the req object within the callback?
passport.use(new FacebookStrategy({
clientID: 123456789,
clientSecret: 'SECRET',
callbackURL: "http://example.com/login/facebook/callback"
},
function(accessToken, refreshToken, profile, done){
// Is there any way to get the req object in here?
}
));
Setting the passReqToCallback option, as so:
passport.use(new LocalStrategy({ passReqToCallback: true },
function(req, username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.verifyPassword(password)) {
req.flash('error', 'Your password is too long');
req.flash('error', 'Also, it is too short!!!');
return done(null, false);
}
return done(null, user);
});
}
));
req becomes the first argument to the verify callback
As per https://github.com/jaredhanson/passport/issues/39
I am answering it too late, but i think my solution is better and more conventional.
In the official documentation here. There is a section "Association in Verify Callback", in which it is mentioned that if we set the strategy's passReqToCallback option to true, this enables req and it will be passed as the first argument to the verify callback.
So my FacebookStrategy now looks like:
var User = require('../models/UserModel.js');
var FacebookStrategy = require('passport-facebook').Strategy;
exports.facebookStrategy = new FacebookStrategy({
clientID: 'REPLACE_IT_WITH_CLIENT_ID',
clientSecret: 'REPLACE_IT_WITH_CLIENT_SECRET',
callbackURL: 'http://localhost:3000/auth/facebook/callback',
passReqToCallback: true
},function(req,accessToken,refreshToken,profile,done){
User.findOne({
'facebook.id' : profile.id
},function(err,user){
if(err){
done(err);
}
if(user){
req.login(user,function(err){
if(err){
return next(err);
}
return done(null,user);
});
}else{
var newUser = new User();
newUser.facebook.id = profile.id;
newUser.facebook.name = profile.displayName;
newUser.facebook.token = profile.token;
newUser.save(function(err){
if(err){
throw(err);
}
req.login(newUser,function(err){
if(err){
return next(err);
}
return done(null,newUser);
});
});
}
});
}
);
In my code sample i have added some logic to save user info in DB and saving user details in session. I thought it might be helpful to people.
req.user gives the information of user stored in passport session.

Resources