2

I am trying to have it so when a user signs up to my site that they get an email saying that they need to verify their email to use the site. It currently sends the email with the token just fine but when I go to the confirmation link it fails with a status 404.

Route

app.post('/confirmation/:token', 
  users.confirmationPost);

Require controller

var users = require('../controllers/users-controller');

confirmationPost

exports.confirmationPost = function (req, res, next) {
    req.assert('email', 'Email is not valid').isEmail();
    req.assert('email', 'Email cannot be blank').notEmpty();
    req.assert('token', 'Token cannot be blank').notEmpty();
    req.sanitize('email').normalizeEmail({ remove_dots: false });

    // Check for validation errors    
    var errors = req.validationErrors();
    if (errors) return res.status(400).send(errors);

    // Find a matching token
    Token.findOne({ token: req.body.token }, function (err, token) {
      if(err) throw err;
        if (!token) return res.status(400).send({ type: 'not-verified', msg: 'We were unable to find a valid token. Your token my have expired.' });

        // If we found a token, find a matching user
        User.findOne({ _id: token._userId }, function (err, user) {
          if(err) throw err;
            if (!user) return res.status(400).send({ msg: 'We were unable to find a user for this token.' });
            if (user.isVerified) return res.status(400).send({ type: 'already-verified', msg: 'This user has already been verified.' });

            // Verify and save the user
            user.isVerified = true;
            user.save(function (err) {
                if (err) { return res.status(500).send({ msg: err.message }); }
                res.status(200).send("The account has been verified. Please log in.");
            });
        });
    });
};

Passport signup

passport.use('signup', new LocalStrategy({
      usernameField: 'email',
      passReqToCallback : true
    },
    function(req, email, password, done) {
      var findOrCreateUser = function(){
        User.findOne({ email: req.body.email }, function(err, existingUser) {
          if(err){
            console.log(err);
          }
          if (existingUser) {
            req.flash('form', {
              email: req.body.email
            });
            return done(null, false, req.flash('error', 'An account with that email address already exists.'));
          }
          // edit this portion to accept other properties when creating a user.
          var user = new User({
            email: req.body.email,
            password: req.body.password // user schema pre save task hashes this password
          });

          user.save(function(err) {
            if (err) return done(err, false, req.flash('error', 'Error saving user.'));

            var token = new Token({ _userId: user._id, token: crypto.randomBytes(16).toString('hex') });
            token.save(function (err) {
            if (err) return done(null, false, req.flash('error', err.message));

            // Send the email
            var message = 'Hello,\n\n' + 'Please verify your account by clicking the link: \nhttp:\/\/' + req.headers.host + '\/confirmation\/' + token.token + '.\n';
            sendEmail('"Phantom Asset Management" noreply@phantomam.com', user.email, 'Account Verification Token', message);
            });
            var time = 14 * 24 * 3600000;
            req.session.cookie.maxAge = time; //2 weeks
            req.session.cookie.expires = new Date(Date.now() + time);
            req.session.touch();
            return done(null, user, req.flash('success', 'A verification email has been sent to ' + user.email + '.'));
          });
        });
      };

      process.nextTick(findOrCreateUser);

    })
  );

When I go to /confirmation/:token I get my error 404 page and nothing in my console. Only thing I see there is my debugger showing an error 404 for that route.

Kirbytech
  • 634
  • 1
  • 5
  • 18
  • It's a `POST`. Did you make sure you sent post request not get? – smac89 Nov 14 '17 at 22:20
  • ... Umm... How would I do that from an email / /link? I use the `sendEmail` function to sent it, the `var message` is what actually gets send. How do I make sure the `/confirmation` route gets the email and the token it needs from when the user follows the link – Kirbytech Nov 14 '17 at 22:21
  • That doesn't tell us much, but it seems you are not even calling the endpoint using `POST`, so the `sendEmail` function is not being called. You need to show exactly how you call this endpoint. We don't have your url to test that for you, so you need to show how it is being called. If you have `curl` installed, open a command prompt and type `curl -X POST /confirmation/1234`. Update your question with the output. Finally create an [mcve (Minimal, Complete, and Verifiable example)](https://stackoverflow.com/help/mcve) and update your post with that. – smac89 Nov 14 '17 at 22:54
  • Using PostMan I get this response when I send a post request `[ { "param": "email", "msg": "Email is not valid" }, { "param": "email", "msg": "Email cannot be blank" } ]` I know I need to send some data but no clue how. Never used postman until today – Kirbytech Nov 14 '17 at 23:00
  • I followed this guide https://codemoto.io/coding/nodejs/email-verification-node-express-mongodb – Kirbytech Nov 14 '17 at 23:03
  • It seems your endpoint needs query params not paths, so it should be like this `app.post('/confirmation')`? Then you pass `email` and `token` using the syntax `/confirmation?email=foo@bar.com&token=1234` – smac89 Nov 14 '17 at 23:22

0 Answers0