Hi, i have a few questions in relation to account activation, which i hope someone can help me with: 01 - when a user creates an account, should we limit the time in which they can activate the account using the link in their email 02 - if so, how should we handle the link if the token no longer appears in the database 03 - is there anything i need to look out for in terms a user misusing the link below www.website.com/activate-account?id=1&token=bd335a180623348g6e40baf50df17a30a67d9ea4 Thanks in advance for your help
Hi oo7ml, Here's what I think. 01 - Limit the time that the user can register to an hour. That way, potential hackers have less time to take advantage of a token. 02 - Use a PHP script similar to this: <?php if(!isset($_POST[token])){ die('No token set.'); } mysql_real_escape_string($_POST[token]); $con = mysql_connect(/*db login info*/); $query = mysql_query("SELECT token FROM tokens WHERE token='$_POST[token]'", $con); if(!mysql_num_rows($query)==1){ //the token does not exist die('Invalid token'); } ?> 03 - I don't see what you mean with that question. Could you be more specific? -Tony
I would not set a time limit to activate an account. Users can sign up for your site on impulse and do not require to use it until a day or two after.
I still believe the time should be one hour. That way, if you snag someone who is unsure about wanting an account, they won't have much time to get away. Also, if you make it so that they have to activate quickly, they are more likely to remember to activate. Once a user has been activated, you should send them to the homepage, so they can start browsing your site (and it's on you to have an easily navigable homepage). If your site is a tool, make sure there is a big button to start using that tool, or a big menu with options. That's just my opinion. -Tony
I also think an hour is good enough. if a person wants to activate an account 2 days later and clicks on the activation link in the email you can easily give them the option to get a new activation link. The one thing I don't agree with tony is the code that he presented. Problems I noticed: 1. It uses mysql functions. according to php.net the usage of mysql functions is discouraged and you should use mysqli or PDO fucntions 2. usage of die - you should really show a proper page not just killing the script. I know Tony you said similar but I still want to point those things out. In addition I would also log IP's that sent wrong activation codes or too many too quickly so that they can be blocked I also would change the email activation link. I would take the id= out. you should make sure that each activation key is only generated once which means that you can get the user from the activation key. I think showing the user id is just too much data that is not needed and might open up your script for attacks.
Well, I did say a script similar. Also, I know about the mysql functions and still need to learn PDO. Also, I think that using die is just fine because I wouldn't waste my time on pretty pages for people trying to exploit my site. The script should be airtight, so there is also no reason no token would be set. -Tony
What about a genuine user that makes a mistake? I think the user should be presented with a nice page shouldn't he? You don't know that. there could be technical hick ups, email filtering could manipulate the email content and so on. NOTHING is airtight on the internet. Better get that into your head. NOTHING IS AIRTIGHT.
It is safe in the database as long as you coded your script with proper data validation. You do not want it stored in a $_SESSION, $_COOKIE, $_GET or $_POST though. If it were not safe in the database, they would be no website that was safe. I generate a string that is MD5() encoded using 4 variables and I email it in a link to the new member and store it with their account data in the database. Then they click their link and my validation script checks teh database for a user with that key and unactivated status. If not activated, the script activates them. If validated, it redirects them to the login page. None of my membership systems have been hacked in the last 15+ years. Use this for data validation: http://php.net/manual/en/book.filter.php
Ok, but what is the advantage of saving it in the database as opposed to the script just checking / processing the token when it is clicked
When it is clicked, how is it going to validate it if you do not have it stored on the server somewhere? Stop and think the steps out. It must be stored on the server and referenced by the user's id , username or email address. In other words, if the token is in the url... then how can the script know who to activate if the token is not also in the database? Each user must have their own token.
The token would be made up of several different things such as a timestamp, secret key, user email... So when the link is clicked the script would breakdown the token and their parts and check it, and if there is a match validate the account Would there be something wrong with this method
Ok you say less secure... so I'll ask again, what is the advantage of saving the token in the database from a security point of view
There is no real security advantage of saving the token in the database. However it helps you to validate the string that is passed by the user when he wants to activate his/her account. Assuming you don't save the token in the database, and the user clicks on the link sent to his email, how would you know if the string returned is valid or not. Thanks.
I'd personally store the key in a table called "awaitingactivation" and make the users account inactive by default and using the email and timestamp to create the key. When the form is submitted, the user is emailed the encrypted key with a cron-job cleaning out all inactivated accounts every 48 hours. When the user clicks the link in the email, they are prompted for their password before activating their account, this would ensure that the correct user is activating the correct account.
Cool, that cron would resolve my problem with users using someone else's email address to sign up, which would result in the owner of that email address not being able to sign up using their email address