Question

You know how all these websites send out links to their new users for them to verify their Email address? I'm trying to set up something like this but after some research I still haven't found a good explanation on how to implement this.

I'm open for plugin recommendations, however most of the plugins I found have a ton of other features that I don't really need.

Without using a plugin, how would I go about adding this to my code?

My approach would be to add a 'Email not verified' attribute to the user meta after signup and send out an email with some kind of verification key to the user. How can I verify if the user actually clicked on that link though?

Thanks for any advice

Was it helpful?

Solution

You can use user_register hook

add_action( 'user_register', 'my_registration', 10, 2 );
function my_registration( $user_id ) {
    // get user data
    $user_info = get_userdata($user_id);
    // create md5 code to verify later
    $code = md5(time());
    // make it into a code to send it to user via email
    $string = array('id'=>$user_id, 'code'=>$code);
    // create the activation code and activation status
    update_user_meta($user_id, 'account_activated', 0);
    update_user_meta($user_id, 'activation_code', $code);
    // create the url
    $url = get_site_url(). '/my-account/?act=' .base64_encode( serialize($string));
    // basically we will edit here to make this nicer
    $html = 'Please click the following links <br/><br/> <a href="'.$url.'">'.$url.'</a>';
    // send an email out to user
    wp_mail( $user_info->user_email, __('Email Subject','text-domain') , $html);
}

You can check for $_GET['act'] and then activate if that's a valid key by updating the meta value account_activated. You can use wp_authenticate_user hook to verify activation status every time when user tries to login.

Snippet to validate:

add_action( 'init', 'verify_user_code' );
function verify_user_code(){
    if(isset($_GET['act'])){
        $data = unserialize(base64_decode($_GET['act']));
        $code = get_user_meta($data['id'], 'activation_code', true);
        // verify whether the code given is the same as ours
        if($code == $data['code']){
            // update the user meta
            update_user_meta($data['id'], 'is_activated', 1);
            wc_add_notice( __( '<strong>Success:</strong> Your account has been activated! ', 'text-domain' )  );
        }
    }
}

OTHER TIPS

Guys I think the above method introduces security vulnerabilities that do not need to be there.

The primary goal of email verification is that we want people who signup to provide a real email address that they own or at least have access to. We do not want people signing up with lets say a random email address that someone else owns, for instance your email address.

The above code has vulnerabilities that could enable a hacker to register a random email address someone else owns and then relevantly easily brute force the $user_id value and the $code value on your email verification page.

1st vulnerability

You are using $user_id. Now I know this value could be any number of things but typically this is going to be an integer especially if using wordpress which is circa 30% of the websites on the internet and looking at the above php code it is indeed based on wordpress. The hacker is either given their $user_id as part of the signup process or else they guess their $user_id via brute force just going up sequentially starting at the number 1 and continuing 2 , 3, 4, 5, 6 ..... they will guess their $user_id in less than a day perhaps in even in less than an hour if your website does not have that many members.

2nd vulnerability

You are creating a $code using the MD5 hashing function and the time of signup. The hacker knows what time they signed up. Let's say the hacker signs-up at 3pm. Now all the hacker has to do is MD5 hash times from 2.55pm to 3.05pm and they will brute force the $code in less than an hour.

Looking at the above the hacker can just brute force the $user_id and $code in less than a day and verify an email address that they do not own

tut tut tut

A better approach would be to generate a $code with the rand() function using uppercase (A-Z) and lower case (a-z), numbers (0-9) and special characters e.g. (!&#). That MD5 hashing function is only using numbers 0-9 and lower case letters a-f and they way ye are using it based on the time of signup is making it incredibly easy to narrow down and brute force attack.

I have written the below PHP code the generate a random $code with Uppercase Letters/Lowercase Letters/Intergers/Special Characters. Don't make it so easy for hackers guys.

function generateRandomString($stringLength){
    //specify characters to be used in generating random string, do not specify any characters that wordpress does not allow in the creation.
    $characters = "0123456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_[]{}!@$%^*().,>=-;|:?";

    //get the total length of specified characters to be used in generating random string
    $charactersLength = strlen($characters);

    //declare a string that we will use to create the random string 
    $randomString = '';

    for ($i = 0; $i < $stringLength; $i++) {
        //generate random characters
        $randomCharacter = $characters[rand(0, $charactersLength - 1)];
        //add the random characters to the random string
        $randomString .=  $randomCharacter;
    };

    //sanitize_user, just in case 
    $sanRandomString = sanitize_user($randomString);

    //check that random string contains Uppercase/Lowercase/Intergers/Special Char and that it is the correct length
    if ( (preg_match('([a-zA-Z].*[0-9]|[0-9].*[a-zA-Z].*[_\W])', $sanRandomString)==1) && (strlen($sanRandomString)==$stringLength) )
    {
        //return the random string if it meets the complexity criteria 
        return $sanRandomString;
    } else {
        // if the random string does not meet minimium criteria call function again 
        return call_user_func("generateRandomString",($stringLength) );
    }
}//end of generateRandomString function

//call the function to generate a random string with Uppercase Letters/Lowercase Letters/Intergers/Special Characters 
//into the function we pass the length of string we require, in this exampe it will generate a string 32 characters long
$code = generateRandomString(32);

echo $code;
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top