I have managed to send an email link to the user upon registration with their email and the token but how would the information be passed to my activation form? I think I would need to use the $_get method but how would I do this? The user has the following email…How would I match their token with the token in my database and their email?
Simplified example, when the user registers to your site you save the user_id and token to db and send the activation link to the user’s email. Lets assume the link would be like https://your.site.com/activate_account.php?user_id=3&token=usersUniqueSecretToken. Now when the user receives your link and follows it to your activation page activate_account.php, two GET will be set on that script.
$_GET['user_id'] // contains value 3
$_GET['token'] // contains value usersUniqueSecretToken
You compare these GET values to the values set in the db at the time of the registration and if they match you set the user account as activated. Otherwise it stays not activated.
I can only get my activation to work with using token but i tried to make the token more secure by using password_hash and then password_verify but can’t get it to work with it… should we hash a token or just set an expiry date for the token?
For some reason, my database is not updating the 0 to 1 but I am receiving the email stating that it has been successfully activated…Also, what is the proper way to concatenate a string variable? Do I use ‘$name’ or ‘“.$name.”’
<?php
if (!isset($_GET['email']) || !isset($_GET['activatetoken'])) {
header("Location: ../index.php?activate=missinglink");
exit();
} else {
include_once 'dbh.php';
// retrieve the email and token from url
$email = mysqli_real_escape_string($conn, $_GET['email']);
$token = mysqli_real_escape_string($conn, $_GET['activatetoken']);
// select information from the database and match it
$sql = "SELECT user_email, user_token FROM users WHERE user_email = '$email' AND user_token = '$token' AND user_activate = 0";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
if($resultCheck > 0) {
$sql = "UPDATE users
SET user_activate = 1, user_token =''
WHERE user_email = '$email'
";
mysqli_query($conn, $sql);
}
}
$mailFrom = "PianoCourse101";
$subject = "Thank you for activating your basic membership account!";
$name = "PianoCourse101";
$mailTo = "piano0011@hotmail.com";
$headers = "From: ".$mailFrom;
$txt = "Thank you for activating your free account! \n\n You can now access your free membership and watch the Bastien piano lessons all for free! If you enjoy your time with us, then feel free to purchase our Level 1, Level 2 and Level 3 course! \n\n At PianoCourse101, we are trying to make your piano learning experience enjoyable and convenient!\n\n Please visit the update profile section to check your details. It is important that the details are correct and if there are any incorrect information, please don't hesitate to email us.";
mail($mailTo, $subject, $txt, $headers);
header("Location: ../index.php?activate=sucess");
exit();
// Send an email to confirm activation of account:
Well, you send the email regardless of whether $resultCheck is larger than 0 or not.
Also, you really do not need the email address in this check, just the token is enough. Get rid of the email address, which will also be in the server logs (since it’s part of the URL), etc. You don’t need it, you don’t want it.
Regarding string concatenation, there are several options, and it mostly boils down to opinion which one you use.
Simple concatenation: 'foo ' . $somevalue . ' bar' - trivial and easy to follow
String intepolation: “foo $somevalue bar” - requires double quotes, and is generally believed to be a tad slower than concatenation, though in the grand scheme of things this is probably negligable.
sprintf: sprintf(‘foo %s bar’, $somevalue); - bit harder to grasp because you need to know that %s is for strings, %d is for integers etc, but extremely easy to read when you do, it’s much easier than the two above, especially for long strings with lots of variables.
However, what you’re doing with your queries should not by solved by string concatenation, but by using prepared queries, as multiple people have told you several times now.
// no longer use mysqli_real_escape_string, it's not safe
//$email = mysqli_real_escape_string($conn, $_GET['email']);
//$token = mysqli_real_escape_string($conn, $_GET['activatetoken']);
$sql = "SELECT user_email, user_token FROM users WHERE user_token = ? AND user_activate = 0";
$stmt = mysqli_prepare($conn, $sql);
mysqli_bind_param($stmt, 's', $_GET['activatetoken']);
mysqli_execute($stmt);
$resultCheck = mysqli_num_rows($stmt);
Using PDO instead of MySQLi would make for much nicer code though. Something to keep in mind.
Can I add the following codes underneath the activation part? I tried to do this one the same page and my email activation was not reliable. However, if I put this on a separate page, then I think it is working…
$mailFrom = "PianoCourse101";
$subject = "Thank you for activating your basic membership account!";
$name = "PianoCourse101";
$mailTo = "piano0011@hotmail.com";
$headers = "From: ".$mailFrom;
$txt = "Thank you for activating your free account! \n\n You can now access your free membership and watch the Bastien piano lessons all for free! If you enjoy your time with us, then feel free to purchase our Level 1, Level 2 and Level 3 course! \n\n At PianoCourse101, we are trying to make your piano learning experience enjoyable and convenient!\n\n Please visit the update profile section to check your details. It is important that the details are correct and if there are any incorrect information, please don't hesitate to email us.";
mail($mailTo, $subject, $txt, $headers);
header("Location: ../index.php?activate=sucess");
exit();
I know that you did say to use phpmailer, I guess that is more reliable to get the code working but it seems tedious to change certain settings…
Like when you finally get around to converting the whole application to something more modern and secure like you repeatedly say you intend to do one day, once you have spent an age creating a “working” but obsolete, insecure and unfit for purpose site?
Avoid tedium and time wasting, do it right first time.