On registering, do not login until verified

#1

Any layman’s way of implementing this: http://docs.meteor.com/#/full/accounts_verifyemail

Not sure where to start as once a user is registered they are automatically logged in. I dont want that. I have whipped up sendgrid and that works, just need to know how to implement Accounts.verifyEmail(token, callback):

// using react

formSubmit(){
 Accounts.createUser('foo@bar.com', 'password');

 // where to verify, prevent from logging in until verified?

}

[SOLVED] Accounts.createUser() changes logged in user
#2

First after creating the user you need to call (on the server):

Accounts.sendVerificationEmail(userId, email);

This sends an email with a verification link to the user.


Next you need to add (this time on the client):

Accounts.onEmailVerificationLink(function(token,done) { 
    Accounts.verifyEmail(token, done);
});

Finally (to block login until email verification is complete), you want Accounts.validateLoginAttempt()

This goes on the server:

Accounts.validateLoginAttempt(function(options) {
    /* options:
        type            (String)    The service name, such as "password" or "twitter".
        allowed         (Boolean)   Whether this login is allowed and will be successful.
        error           (Error)     When allowed is false, the exception describing why the login failed.
        user            (Object)    When it is known which user was attempting to login, the Meteor user object.
        connection      (Object)    The connection object the request came in on.
        methodName      (String)    The name of the Meteor method being used to login.
        methodArguments (Array)     An array of the arguments passed to the login method
    */

    // If the login has failed, just return false.
    if (!options.allowed) {
        return false;
    }

    // Check the user's email is verified. If users may have multiple 
    // email addresses (or no email address) you'd need to do something
    // more complex.
    if (user.emails[0].verified === true) {
        return true;
    } else {
        throw new Meteor.Error('email-not-verified', 'You must verify your email address before you can log in');
    }

});

You can basically check anything inside the validateLoginAttempt callback, so do what works for you.


We actually overwrote the Accounts.sendVerificationEmail / sendEnrollmentEmail / sendResetPasswordEmail functions so we could send with the Mandrill API, and customise the URLs. We then just have a standard IronRouter route that calls Accounts.verifyEmail when the route loads.

Inside validateLoginAttempt we check things like ‘is a user banned?’ ‘are they allowed to access this app?’. Then we do email verification in a separate part of the app (the permissions service), because we want the user to be allowed to login but with limited permissions if they haven’t validated their email address. This way we could let them configure their account or resend the verification email but not actually access any features.

2 Likes
#3

Splendid.

I was on the right track but the user could still login then sees a message that says to click to verify. Not sure to have them be able to browse around for x time before needed to verify their email. I’ll have a think but thanks for this information.

#4

can you please tell me how can I catch that “email-not-verified” error on the client side?

so I can tell the user he should verify his email or even tell him to wait until the admin approves his registration.

thanks for any help you are able to provide.

#5

You can get it in the callback function :

Meteor.loginWithPassword({email}, password, (err) => {
			if (err) {
				console.log(err);
				this.setState({
					error: err.reason || err.error
				})
			}
		})