it-swarm.com.de

Passwort zurücksetzen in NodeJS

Ich habe ein Update vorgenommen, um das Passwort eines Benutzers mit NodeJS/Passport zu aktualisieren. Ich folgte diesem großartigen Leitfaden: http://sahatyalkabov.com/how-to-implement-password-reset-in-nodejs/ .

99% davon arbeiten. Ich musste es ein wenig modifizieren, um einige Stripe-Funktionen zu integrieren. Ich befürchte jedoch, ich habe irgendwo einen kritischen Fehler und kann ihn nicht finden. Der Benutzer kann derzeit den gesamten Vorgang des Versendens einer E-Mail durchgehen, ein neues Kennwort eingeben und angemeldet sein. Eine weitere E-Mail sagt, dass das Kennwort erfolgreich aktualisiert wurde. Alles perfekt. Jedoch. Aus irgendeinem Grund. Das neue Passwort wird nicht gespeichert. Der Benutzer kann sich nur mit seinem alten Passwort anmelden. Ich habe alles versucht, um das zu beheben.

Ich habe mir mehrere andere Programmierer angeschaut, und keiner von ihnen konnte herausfinden, wie es auf der Welt nicht funktioniert. 

Der gegenwärtige Gedanke ist, dass die Sitzung möglicherweise nicht korrekt beendet wird, aber wir haben versucht, die Sitzung zu zerstören, und sie funktionierte trotzdem nicht. 

Jede Hilfe sehr geschätzt. 

Vollständiger Aufbau:

Benutzermodell:

var UserSchema = new mongoose.Schema({
    username:   { type: String, required: true, unique: true },
    password:  String,
    datapoint:  String,
    email:  { type: String, required: true, unique: true },
    resetPasswordToken: String,
    resetPasswordExpires: Date
});


UserSchema.pre('save', function(next) {
  var user = this;
  var SALT_FACTOR = 5;

  if (!user.isModified('password')) return next();

  bcrypt.genSalt(SALT_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();
    });
  });
});

Neues Konto registrieren(Dies hat auch Stripe-Informationen in keinem Zusammenhang, könnte jedoch das Problem verursachen.)

var newUser = new User({username: req.body.username, email: req.body.email, datapoint: req.body.datapoint});
      User.register(newUser, req.body.password, function(err, user){


            if(err){
            console.log('Looks like there was an error:' + ' ' + err)
             res.redirect('/login')

          } else {
          passport.authenticate("local")(req, res, function(){

      var user = new User({
      username: req.body.username,
      email: req.body.email,
      password: req.body.password

      })


console.log('creating new account')
console.log('prepping charge')
var token = req.body.stripeToken; // Using Express
var charge = stripe.charges.create({
  amount: 749,
  currency: "usd",
  description: "Example charge",
  source: token,

}, function(err, charge) {
  // asynchronously called
  console.log('charged')
});
            res.redirect('/jobquiz')
             console.log(req.body.datapoint)
             console.log(req.body.email)

          });
          }
      });
});

Passwort-Posting einrichten

app.post('/forgot', function(req, res, next) {
  async.waterfall([
    function(done) {
      crypto.randomBytes(20, function(err, buf) {
        var token = buf.toString('hex');
        done(err, token);
      });
    },
    function(token, done) {
      User.findOne({ email: req.body.email }, function(err, user) {
        if (!user) {
        //   console.log('error', 'No account with that email address exists.');
        req.flash('error', 'No account with that email address exists.');
          return res.redirect('/forgot');
        }
console.log('step 1')
        user.resetPasswordToken = token;
        user.resetPasswordExpires = Date.now() + 3600000; // 1 hour

        user.save(function(err) {
          done(err, token, user);
        });
      });
    },
    function(token, user, done) {
        console.log('step 2')


      var smtpTrans = nodemailer.createTransport({
         service: 'Gmail', 
         auth: {
          user: 'myemail',
          pass: 'mypassword'
        }
      });
      var mailOptions = {

        to: user.email,
        from: 'myemail',
        subject: 'Node.js Password Reset',
        text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
          'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
          'http://' + req.headers.Host + '/reset/' + token + '\n\n' +
          'If you did not request this, please ignore this email and your password will remain unchanged.\n'

      };
      console.log('step 3')

        smtpTrans.sendMail(mailOptions, function(err) {
        req.flash('success', 'An e-mail has been sent to ' + user.email + ' with further instructions.');
        console.log('sent')
        res.redirect('/forgot');
});
}
  ], function(err) {
    console.log('this err' + ' ' + err)
    res.redirect('/');
  });
});

app.get('/forgot', function(req, res) {
  res.render('forgot', {
    User: req.user
  });
});

Passwortwechsel einrichten

app.get('/reset/:token', function(req, res) {
  User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
      console.log(user);
    if (!user) {
      req.flash('error', 'Password reset token is invalid or has expired.');
      return res.redirect('/forgot');
    }
    res.render('reset', {
     User: req.user
    });
  });
});




app.post('/reset/:token', function(req, res) {
  async.waterfall([
    function(done) {
      User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user, next) {
        if (!user) {
          req.flash('error', 'Password reset token is invalid or has expired.');
          return res.redirect('back');
        }


        user.password = req.body.password;
        user.resetPasswordToken = undefined;
        user.resetPasswordExpires = undefined;
        console.log('password' + user.password  + 'and the user is' + user)

user.save(function(err) {
  if (err) {
      console.log('here')
       return res.redirect('back');
  } else { 
      console.log('here2')
    req.logIn(user, function(err) {
      done(err, user);
    });

  }
        });
      });
    },





    function(user, done) {
        // console.log('got this far 4')
      var smtpTrans = nodemailer.createTransport({
        service: 'Gmail',
        auth: {
          user: 'myemail',
          pass: 'mypass'
        }
      });
      var mailOptions = {
        to: user.email,
        from: 'myemail',
        subject: 'Your password has been changed',
        text: 'Hello,\n\n' +
          ' - This is a confirmation that the password for your account ' + user.email + ' has just been changed.\n'
      };
      smtpTrans.sendMail(mailOptions, function(err) {
        // req.flash('success', 'Success! Your password has been changed.');
        done(err);
      });
    }
  ], function(err) {
    res.redirect('/');
  });
});
13
AndrewLeonardi

Ich habe (oder habe) kein Problem mit Ihrem Code gefunden, aber ich habe den Vorschlag, den Fehler aufzuspüren.

Dieser Codeblock ist riskant. Sie können das Kennwortfeld versehentlich aktualisieren und den Rehash-Kennwortvorgang auslösen.

UserSchema.pre('save', function(next) {
   var user = this;
   var SALT_FACTOR = 12; // 12 or more for better security

   if (!user.isModified('password')) return next();

   console.log(user.password) // Check accident password update

   bcrypt.genSalt(SALT_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();
      });
   });
});

Setzen Sie einen console.log direkt nach der if (!user.isModified('password')), um nach unerwarteten Kennwortaktualisierungen zu suchen. Versuchen Sie nun erneut, das Passwort zu vergessen, und prüfen Sie, ob ein Fehler vorliegt.

* TD; LR Separates Aktualisierungskennwort in eine neue Methode, anstatt es in den Vorab-Speicher zu stellen, da Sie versehentlich ein neues Kennwort zusammen mit anderen Feldern aktualisieren können

* Update: Danke #imns für den Vorschlag einer besseren SALT_FACTOR-Nummer.

6
Anh Cao

Ich denke, das Problem könnte in der Hash-Funktion liegen. Ich habe versucht, Ihren Code in einem einfacheren, aber ähnlichen Experiment auf meinem Computer zu duplizieren.

Wie die Dokumente von bcrypt hier angeben: https://www.npmjs.com/package/bcrypt#to-hash-a-password

Die Hash-Funktion nimmt nur 3 Argumente auf, die Sie in 4 einschicken. Das dritte Argument in Ihrem Fall ist null.

Hier ist ein Code, um das Problem und die hoffentlich Lösung zu veranschaulichen

Im salzigen Callback

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

Ändern Sie das dritte Argument jedoch stattdessen in die Rückruffunktion. 

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

Ich hatte das gleiche Problem, löschte einfach den Null-Parameter aus dieser Zeile:

bcrypt.hash (user.password, salt, null, function (err, hash) {

1
user9348495

Ich habe diesen Code bereits in meinem aktuellen Projekt verwendet, und es funktioniert gut. Ich habe einen kleinen Fehler in Ihrem Code in der Funktion UserSchema.pre('save', function(next) gesehen. Wenn Sie das Passwort mit bcrypt.hash hash, dann hat es vier Argumente, aber es gibt nur drei Argumente in meinem Code 

schema.pre('save', function(next) {
    var user = this;
    var SALT_FACTOR = 5;

    if(!user.isModified('password')){
        return next();
    }

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

Das dritte Argument muss die Callback-Funktion sein. Siehe Dokument für bcrypt

0
Gaurav