Closed bhanuc closed 10 years ago
The usage of the 'local' strategy is shown in the example. What is your exact problem?
Ah, okay, you are talking about a sign up and not a login functionality, I read over that. Could you please format your code example properly?
sorry it was formatted very poorly ... I am trying to create the signup code in auth.js which can be called from main aplication in routes
@bhanuc assuming that User
is your model (I am using mongoose) and that you are using email
(in my case) as username, here is how you can do it:
// Signin with email
passport.use('local-signin', new LocalStrategy({
usernameField : 'email'
},
function using(email, password, done) {
User.findOne({ 'email': email }, function findOne(err, user) {
if (err) return done(err);
if (!user) done(null, false);
user.verifyPassword(user.local.hash, password, function verifyPassword(err, valid) {
if (err) return done(err);
if (!valid) return done(null, false);
done(null, user);
});
});
}
));
Notice the passReqToCallback: true
below, with this option you get access to the request object and so to req.body
to get your POST
data.
// Signup with email
passport.use('local-signup', new LocalStrategy({
usernameField : 'email',
passReqToCallback : true
},
function using(req, email, password, done) {
if (!req.user) {
User.findOne({ 'email': email }, function findOne(err, user) {
if (err) return done(err);
if (user) return done(null, false);
// account information is in req.body
// you can do your data validation here.
delete req.body.password;
user = new User(req.body);
user.generateHash(password, function generateHash(err, hash) {
if (err) return done(err);
user.hash = hash;
user.save(function save() {
if (err) return done(err);
done(null, user);
});
});
});
} else {
user = req.user;
user.generateHash(password, function generateHash(err, hash) {
if (err) return done(err);
user.hash = hash;
user.save(function save() {
if (err) return done(err);
done(null, user);
});
});
}
}
));
Then use local-signin
and local-signup
in your routes accordingly with:
passport.authenticate('local-signin', {
successRedirect: '/account',
failureRedirect: '/signin'
});
passport.authenticate('local-signup', {
successRedirect: '/account',
failureRedirect: '/signup'
});
Hope this helps!
Here is how your routes can look like:
var parse = require('co-body');
// ...
// ...
var parser = function *parser(next) {
this.req.body = yield parse(this);
yield next;
};
// POST /signin
public.post('/signin',
parser,
passport.authenticate('local-signin', {
successRedirect: '/account',
failureRedirect: '/signin'
})
);
// POST /signup
public.post('/signup',
parser,
passport.authenticate('local-signup', {
successRedirect: '/account',
failureRedirect: '/signup'
})
);
Thanks this is awesome :)
@cayasso Hi , do I need to add a custom hash function too ? I 'cause I am getting an error why I try to use signup route
@bhanuc Yes, the code above is just an example but use your own password hashing and verification module. http://node-modules.com/search?q=hash+password the one in the example is https://github.com/dilvie/credential
Here is my generate function -->
User.prototype.generateHash = function (password, cb) {
console.log(cb);
if (!password) return cb('');
var encrypred
var salt = Math.round((new Date().valueOf() * Math.random())) + '';
this.salt = salt;
try {
encrypred = crypto.createHmac('sha1', salt).update(password).digest('hex')
return cb(encrypred);
} catch (err) {
return cb(err);
}
}
and my signup-method -->
passport.use('local-signup', new LocalStrategy({
usernameField : 'email',
passReqToCallback : true
},
function using(req, email, password, done) {
if (!req.user) {
User.findOne({ 'email': email }, function findOne(err, user) {
if (err) return done(err);
if (user) return done(null, false);
// account information is in req.body
// you can do your data validation here.
delete req.body.password;
user = new User(req.body);
user.generateHash(password, function generateHash(err, password) {
if (err) return done(err);
user.hash = password;
user.save(function save() {
if (err) return done(err);
return done(null, user);
});
}
);
});
} else {
user = req.user;
user.generateHash(password, function generateHash(err, password) {
if (err) return done(err);
user.hash = password;
user.save(function save() {
if (err) return done(err);
done(null, user);
});
});
}
}
));
but I am getting my route gets stuck when I try to signup
@bhanuc Callbacks in node has this signature callback(error, result)
so change cb(encrypted);
to cb(null, encrypted)
in your generateHash
method.
ohh thanks :+1: btw other returns in generateHash method should I also follow the same convention? so what should I return in other callbacks, that is in err I am returning cb(err), would it become cb(err,null) and for (!password) I am returning cb(' '), should I return cb(' ', null). I am confused in this one as both empty string and null are falsey values .
@bhanuc you can find a great introduction to callbacks here https://github.com/maxogden/art-of-node#callbacks
If you follow node convention the first argument is for error, for example cb(new Error('Invalid password'))
I always stick to this to avoid confusion.
// Errors
cb('Something failed'); // not recommended
cb(true); // not recommended
cb(new Error('Something failed')); // be explicit with your error
// Success
cb(null, true);
cb(null, false);
cb(null, user);
cb(null);
cb();
Check passport custom callbacks http://passportjs.org/guide/authenticate/ More on callbacks http://www.devthought.com/2011/12/22/a-string-is-not-an-error/
Hope this helps!
@cayasso Thanks for your awesome help :+1:
I want to create something like
How do I implement this and what do I write in route code. Thanks