views:

99

answers:

6

When a user subscribes to my newsletter via their email address, using php, how would I send them an 'Activation Link' via email to confirm it is their email address and not a fake one.

so at the moment I have

PHP:

<?php
 $to = "[email protected]";
 $subject = "Hi!";
 $body = "Hi,\n\nHow are you?";
 if (mail($to, $subject, $body)) {
   echo "<p>Message successfully sent!</p>";
  } else {
   echo "<p>Message delivery failed...</p>";
  }
 ?>

I guess i would change the $body to this:

$body = "Please click the link to activate your email \n
http://www.activationlink.com?";

How would I make it so that if a user clicked that link it would add their details to the Mysql database recognising they are a legitimate subscriber?

Any help or suggestions appreciated. Thanks

+5  A: 

Insert the user into a table with a 'pending' flag set (or a 'validated' flag not set). They should not be able to do anything until the flag is changed. If you want to be really thorough, actually put them into a users_temp table. Generate a totally random key and associate it with their user ID. The link you email to them should be http://yourwebsite.com/?activate=totallyrandomkeyigeneratedearlier. When you get an activation request, turn on the valid flag for the user with the corresponding random key.

Borealid
In case you send out eMails when the account has been activated, consider deleting the id after the activation or check if it was previously activated. I had one system where calling the activation link would always trigger an eMail and one user had the URL opened in a browser tab for days. Whenever he restarted his browser and the tabs got restored, he would get a new activation confirmation.
Gordon
+3  A: 

What I like to do is:

  • Generate a unique, random ID in the registration process

  • Store the ID along with the E-Mail address, a "confirmed" field (default: "no") and any additional data in a database table

  • Send out the E-Mail with an URL pointing to activate the unique ID (e.g. domain.com/activate.php?id=102939505595

  • The activation page checks whether the unique key exists and changes the confirmed field to yes (or 1 or whatever).

  • Additionally and optionally, save the confirmation date/time, IP address and user agent.

Pekka
A: 

Personally I would add there details to the database and have a fields called "active" then when they click the activation link all you need to do is update this one field.

You could also have a "This was not me" link in the email and if they click this you remove all there details.

Alistair Prestidge
interesting idea about this was not me
Ryan Murphy
A: 

Generate a unique ID and store this together with the username/password within some temporary database entry for the new user.

$tmpID = uniqid();

Then, adapt the link in you eMail-body to e.g:

$body = "Please click the link to activate your email \n
http://www.activationlink.com/activateAccount?activate=".$tmpID;

If the user requests /activateAccount on your server, check the database entry against the $_GET['activate'] parameter, and set the user activated (if it matches).

In order to make sure your database does not just get more and more entries, you could use a cron-job who clears entries older than e.g. 24h.

Javaguru
This may be open to attack, since uniqid() is predictable. Make sure you use the more_entropy flag at least.
Marcus Adams
I agree, the *more_entropy* flag makes it more secure.But anyhow, if you don't have direct access to the server, it will be quite hard to determine the exact time! (Since uniquid() is based on the microseconds of the current time!!). So, if no direct access is possible, the attacker must try a lot of keys in order to find the correct one. Thus, a limitation of the number of allowed activation-trials for the account would probably be sufficient to prevent an attack, and should generally be considered as a good practice.
Javaguru
A: 

Firstly you will need to add 2 column to your database table that holds the users

The column should be called active and activation_hash

When the user registers you need to insert the user to the DB but set the active to 0 and the activation_hash becomes some random md5 of the users email_address,first_name etc with a unique_id() in there, make sure its in MD5 Format and then store that in the activation_hash column.

In your email template add the link for the user to activate such as:

<a href="http://mydomain.registrer.php?process=activate&amp;id=&lt;?php echo $user_id;?>&hash=<?php echo $activation_hash;?>">Activate your account</a>

Then inside your register file or wherever you your pointing the activation link to, just get the user_id & the activation hash via $_GET and validate against your db.

if they do not match then ask the user to enter his password to send another activation hash. otherwise set the column active to 1 so that the rest of your application knows what status the user is.

thats basically it.

RobertPitt
You should hash against a random value over simply a unique id. If the link includes the user id, you don't need it to be unique, and the MD5 hash guarantees that it's not unique anyway. It would be better to hash against a random value, or simply use a random value without the hash.
Marcus Adams
was that targeted at my post or was it just extra information, if so then I did explain that the has should consist of a array of data thats unique to that user as-well as some uniqe_id();
RobertPitt
@Robert, it's important to point out the difference between unique and random. A random key of sufficient length would be preferred over a unique one.
Marcus Adams
@Marcus, Your right, I should of gone into a little bit more depth.
RobertPitt
+1  A: 

no database needed. you can send all data in the hyperlink signed by hash

I've answered similar question recently even with expiration time.
though it was for the password recovery link, but idea is the same

$token = sha1($time.$email.$salt).dechex(time()).dechex($user_id);
$link = "http://".$domain."/restorepass/?token=$token";

whole token would looks like single hexdecimal number and it would be hard to guess it's meaning.

upon receive just split and decode it back.
Neat, IMO.

Col. Shrapnel
You'll still need to store whether the user is activated or not. However, as pointed out, you don't need to store a hash.
Marcus Adams
@Marcus you can create user account at the time it's activated. that's all
Col. Shrapnel
@Col. Shrapnel, That's a neat idea, and definitely low maintenance. The implication is that the hash is completely based on user supplied data, so it would need to be hashed against some secret key in order to avoid abuse, or, you said signed, so maybe some asymmetric algorithm.
Marcus Adams
Javaguru
@Marcus yeah some salt should be added.
Col. Shrapnel