Подтверждение электронной почты с токеном в файле passport.js

Я просто ищу решение, которое делает проверку электронной почты с токеном для моей локальной авторизации в файле passport.js Есть ли какой-либо плагин или компонент для node, который может упростить проверку? Или я должен сделать это сам?

Мой контроллер

exports.postSignup = function(req, res, next) {
  req.assert('email', 'Email is not valid').isEmail();
  req.assert('password', 'Password must be at least 4 characters long').len(4);
  req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password);

  var errors = req.validationErrors();

  if (errors) {
    req.flash('errors', errors);
    return res.redirect('/signup');
  }

  var user = User.build({
    email: req.body.email,
    password: req.body.password,
  });

  User
  .find({ where: { email: req.body.email } })
  .then(function(existingUser){
    if (existingUser) {
      req.flash('errors', { msg: 'Account with that email address already exists.' });
      return res.redirect('/signup');
    }

    user
    .save()
    .complete(function(err){
      if (err) return next(err);
      req.logIn(user, function(err){
        if (err) return next(err);
        res.redirect('/');
      });
    });
  }).catch(function(err){
    return next(err);
  });
};

Спасибо за любое мнение!

Ответ 1

Реализация этого сама по себе довольно проста.

Псевдокод:

//A user registers
    //User is stored along with a random token string and a variable set to false
    //User is sent a verification email

//Verification email has a link with the random token and a unique ID for that user

//Link goes to a route that takes the token as a parameter


//Match the user and the random token

//If they match - change a variable to verified

Пакет, который я использую для генерации случайной строки: https://www.npmjs.com/package/randomstring

Локальная стратегия регистрации

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) {
        // asynchronous
        // User.findOne wont fire unless data is sent back
        process.nextTick(function () {
            // 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.findOne({'local.email': email}, function (err, user) {
                // if there are any errors, return the error
                if (err) {
                    return done(err);
                }

                // check to see if theres already a user with that email
                if (user) {
                    console.log('that email exists');
                    return done(null, false, req.flash('signupMessage', email + ' is already in use. '));

                } else {
                    User.findOne({'local.username': req.body.username}, function (err, user) {
                        if (user) {
                            console.log('That username exists');
                            return done(null, false, req.flash('signupMessage', 'That username is already taken.'));
                        }

                        if (req.body.password != req.body.confirm_password) {
                            console.log('Passwords do not match');
                            return done(null, false, req.flash('signupMessage', 'Your passwords do not match'));
                        }

                        else {
                            // create the user
                            var newUser = new User();

                            var permalink = req.body.username.toLowerCase().replace(' ', '').replace(/[^\w\s]/gi, '').trim();

                            var verification_token = randomstring.generate({
                                length: 64
                            });


                            newUser.local.email = email;

                            newUser.local.password = newUser.generateHash(password);

                            newUser.local.permalink = permalink;

                            //Verified will get turned to true when they verify email address
                            newUser.local.verified = false;
                            newUser.local.verify_token = verification_token;

                            try {
                                newUser.save(function (err) {
                                    if (err) {

                                        throw err;
                                    } else {
                                        VerifyEmail.sendverification(email, verification_token, permalink);
                                        return done(null, newUser);
                                    }
                                });
                            } catch (err) {

                            }
                        }
                    });
                }
            });
        });
    }));

Я использую комбинацию /permalink/random -token для URL-адреса проверки

Маршрут должен выглядеть следующим образом:

app.get('/verify/:permaink/:token', function (req, res) {
        var permalink = req.params.permaink;
        var token = req.params.token;

        User.findOne({'local.permalink': permalink}, function (err, user) {
            if (user.local.verify_token == token) {
                console.log('that token is correct! Verify the user');

                User.findOneAndUpdate({'local.permalink': permalink}, {'local.verified': true}, function (err, resp) {
                    console.log('The user has been verified!');
                });

                res.redirect('/login');
            } else {
                console.log('The token is wrong! Reject the user. token should be: ' + user.local.verify_token);
            }
        });
    });