web-dev-qa-db-fra.com

Passeport: Autoriser l'inscription avec nom et adresse email? (Stratégie locale)

Est-il possible d'autoriser un utilisateur à s'enregistrer sur la stratégie locale avec son mot de passe, son adresse email et son nom?
Tous les exemples que je pouvais trouver en ligne n’utilisaient que nom/mot de passe ou email/mot de passe. 

J'ai également parcouru l'ensemble de la documentation du passeport, mais cette documentation n'est d'aucune utilité. Ce n'est qu'un site gonflé plein d'exemples.
J'ai juste besoin d’une liste de fonctions, de classes et de variables que passeport utilise avec des explications sur ce qu’elles et tous leurs paramètres font. Chaque bonne bibliothèque a quelque chose comme ça, pourquoi ne puis-je pas le trouver comme passeport?

Voici les parties clés de mon code:

passport.use('local-signup', new LocalStrategy({
    usernameField: 'email',
    passwordField: 'password',
    //are there other options?
    //emailField did not seem to do anything
    passReqToCallback: true // allows us to pass in the req from our route (lets us check if a user is logged in or not)
},
function(req, email, password, done) {
    //check if email not already in database
        //create new user using "email" and "password"
        //I want an additional parameter here "name"
}));

Alors, le passeport est-il vraiment limité? Il doit y avoir un moyen de faire cela, non?

12
Forivin

Vous pouvez être un peu confus, mais passeport n’implémente pas les méthodes d’inscription. C'est juste une bibliothèque d'autorisation. Vous devez donc gérer vous-même ce cas d'utilisation.

Tout d’abord, créez un itinéraire qui sera responsable de votre inscription et de vos contrôles:

signup: function (req, res) {
  User
    .findOne({
      or: [{username: req.param('username')}, {email: req.param('email')}]
    })
    .then(function(user) {
      if (user) return {message: 'User already exists'};          
      return User.create(req.allParams());
    })
    .then(res.ok)
    .catch(res.negotiate);
}

L'exemple ci-dessus est basé sur le framework Sails, mais vous pouvez l'adapter sans problème à votre propre cas.

La prochaine étape consiste à inclure une stratégie locale de passeport.

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;

var LOCAL_STRATEGY_CONFIG = {
  usernameField: 'email',
  passwordField: 'password',
  session: false,
  passReqToCallback: true
};

function _onLocalStrategyAuth(req, email, password, next) {
  User
    .findOne(or: [{email: email}, {username: email}])
    .then(function (user) {
      if (!user) return next(null, null, {
        code: 'E_USER_NOT_FOUND',
        message: email + ' is not found',
        status: 401
      });

      if (!HashService.bcrypt.compareSync(password, user.password)) return next(null, null, {
        code: 'E_WRONG_PASSWORD',
        message: 'Password is wrong',
        status: 401
      });

      return next(null, user, {});
    })
    .catch(next);
}

passport.use(new LocalStrategy(LOCAL_STRATEGY_CONFIG), _onLocalStrategyAuth));

Nous n'avons plus que la tâche de connexion maintenant. C'est simple.

signin: function(req, res) {
  passport.authenticate('local', function(error, user, info) {
    if (error || !user) return res.negotiate(Object.assign(error, info));
    return res.ok(user);
  })(req, res);
}

Cette méthode est plus appropriée pour un passeport et fonctionne parfaitement pour moi.

19
ghaiklor

Voici ce qui a fonctionné pour moi, la solution est basée sur un odm basé sur la mangouste, la première partie est la partie relative au passeport.

Si j'ai bien compris votre question, vous voulez que l'utilisateur tape soit son email, soit son mot de passe. Dans ce cas, modifiez la recherche pour essayer les deux, c'est-à-dire faites correspondre l'identifiant d'utilisateur fourni (dans votre appel à findOne (...) avec le nom d'utilisateur ou le mot de passe.

Notez que j'utilise bcrypt pour éviter de stocker des mots de passe clairs, c'est pourquoi il existe une méthode de comparaison personnalisée pour tester les mots de passe. Notez également les «astuces» relatives à l’utilisation de google auth. Mon système a activé les deux, s’il est pertinent, merci de le savoir et je peux ajouter le code requis.

------------ Auth part (juste des extraits pertinents) -----------

var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;

passport.serializeUser(function(user, done) {
    // the values returned here will be used to deserializeUser
    // this can be use for further logins
    done(null, {username: user.username, _id: user.id, role: user.role});
});

passport.deserializeUser(function(user, done) {
    done(null, user);
});


passport.use(new LocalStrategy(function(username, password, done){
    odm.User.findOne({username: username, authType: 'direct'}, function(err, user){
        if(err){
            return done(err, false);
        }
        if(!user){
            return done(null, false);
        }
        if(user.role === 'new'){
            console.log('can not use new user!');
            return done('user not activated yet, please contact admin', false);
        }
        user.comparePassword(password,function(err, isMatch){
            if(err){
                return done(err, false);
            }
            if(isMatch){
                return done(null, user);//{username: username});
            }
            return done(null, false);
        });
    });
}));
app.post('/login',  function(req, res, next){
        passport.authenticate('local', {
            failureRedirect: '/logout?status=login failed'
        }, function(err, user, info){
                if(err){
                    return next(err);
                }
                if(!user){
                    return res.redirect('/login');
                }
                req.logIn(user, function(err){
                    if (req.body.rememberme) {
                        req.session.cookie.maxAge = 30*24*60*60*1000 ;//Rememeber 'me' for 30 days
                    } else {
                        req.session.cookie.expires = false;
                    }
                    var redirect = req.param('redirect') || '/index';
                    res.redirect(redirect);
                });
            }
        )(req, res, next);
    }
);

app.post('/register',function(req, res){
    var user = new odm.User({username: req.body.username, password: req.body.password, email: req.body.email, authType: 'direct'});
    user.save(function(err, user){
        if(err){
            console.log('registration err: ' , err);
        } else {
            res.redirect('/list');
        }
    });
});

--- utilisateur/odm, pièces pertinentes ----------------

var bcrypt = require('bcrypt-nodejs');

// --------------------- User ------------------------------------------ //
var userSchema = new Schema({
    name: String,
    email: String,
    username: {type: String, required: true, unique: true},
    password: String,
    role: {type: String, required: true, enum: ['new', 'admin', 'user'], default: 'new'},
    authType: {type: String, enum: ['google', 'direct'], required: true}
});

userSchema.pre('save', function (next) {
    var user = this;
    if (!user.isModified('password')) return next();

    console.log('making hash...........');
    bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
        if (err) return next(err);

        bcrypt.hash(user.password, salt, null, function (err, hash) {
            if (err) return next(err);
            user.password = hash;
            next();
        });
    });
});

userSchema.methods.comparePassword = function (candidatePassword, cb) {
    bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
        if (err) return cb(err);
        cb(null, isMatch);
    });
};
4
Meir
var localStrategy = require('passport-local').Strategy;
var User = require('../public/models/user');

module.exports = function(passport){

    passport.serializeUser(function(user, done){
        done(null, user.id);
    });

    passport.deserializeUser(function(id, done){
        User.findById(id, function(err, user){
            done(err, user);
        });
    });

    passport.use('local-signup', new localStrategy({
        usernameField: 'email',
        passwordField: 'password',
        passReqToCallback: true
    },
    function(req, email, password, done){
        process.nextTick(function(){
             User.findOne({'local.enroll': email}, function(err, user){
                 if(err)
                     return done(err);
                 if(user){
                     return done(null, false, req.flash('signupmessage', 'The email already taken'));
                 } else{
                     var newUser = new User();
                     newUser.local.enroll = email;
                     newUser.local.password = newUser.generateHash(password);                     
                     newUser.save(function(err){
                         if(err)
                             throw err
                         return done(null, newUser);
                     });
                 }

             });
        });
    }));

    passport.use('local-login', new localStrategy({
        usernameField: 'email',
        passwordField: 'password',
        passReqToCallback: true
    },
    function(req, email, password, done){
        process.nextTick(function(){
             User.findOne({'local.enroll': 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', 'Invalid password'));
                 }
                 return done(null, user);
             });
        });
    }));    
}
1
Mohammad Amir

Cela n'a en fait rien à voir avec passport et est assez simple, en supposant que vous utilisez body-parser. Assurez-vous que vous avez un input field dans votre formulaire avec l'attribut name="name" où vous enregistrez le nom de l'utilisateur comme:

<div class="form-group">
    <label for="signup-name">Name</label>
    <input type="text" placeholder="Name" name="name">
</div> 

Dans votre routage, vous pouvez accéder à ce champ avec req.body.name:

passport.use('local-signup', new LocalStrategy({
    usernameField: 'email',
    passwordField: 'password',
    //are there other options?
    //emailField did not seem to do anything
    passReqToCallback: true
},
function(req, email, password, done) {
    //check if email not already in database
    //create new user using "email" and "password"
    //I want an additional parameter here "name"

    user.email = email;
    user.password = password; // Do some hashing before storing

    user.name = req.body.name;

}));

Vous pouvez donc ajouter autant de champs de saisie de formulaire que vous le souhaitez et y accéder par la valeur de l'attribut name. Un deuxième exemple serait:

<input type="text" placeholder="City" name="city">
<input type="text" placeholder="Country" name="country">

// Access them by
user.city = req.body.city;
user.country = req.body.country;
1
UserModel.find({email: req.body.email}, function(err, user){                                               
    if(err){                                                                  
       res.redirect('/your sign up page');                                                                          
    } else {                                                                  
      if(user.length > 0){                                                    
       res.redirect('/again your sign up page');                                                                      
      } else{                                                               
        //YOUR REGISTRATION CODES HERE                                                                     
       }                                                                          
    }                                                                        
})
0
Y. Alimatov