I am trying to create a forgot password feature which will expire the link created after x hours. So I am storing time() data in database value when a user requests a password reset. So how can I expire it?

what cost you more ? just keep trying to hit the salt/ts and hit the webserver or do the same but keep hitting the db just to check the ts. If you ask me I prefer to reach only the webserver. I think that is the question regarding what approach use. Nothing is absolute
–
Gabriel SosaJun 2 '11 at 15:34

I can derive yoursupersalt by creating one valid account and resetting it's password. Thus I will always hit the DB and can reset random passwords using account id's. Secondly I can request an infinite number of resets on one account unless you flag the account for being 'in reset' during link creation.
–
MelJun 2 '11 at 15:48

You're probably having a table entry with a reset link, just add a date field to it, and then either include a WHERE expiredate<NOW() or clean the table from time to time with a simple DELETE from table WHERE expiredata<NOW().

One method of doing this is to check to see if the link is expired when the link is clicked -- some pseudo-code:

// when the link is clicked pull the information from the database and get the time
// SQL goes here
// this will give you the difference in seconds
$diff = time() - $timestamp_from_db;
// we'll pretend the time expires in 8 hours
$expires_in = 8 * 60 * 60;
// for this example we'll pretend the expiration is 8 hours
if($diff <= $expires_in)
{
// has not been more then 8 hours
}
else
{
// has been more then 8 hours
}

The best way to do this that keeps the table clean is to implement the following:

The table needs at least the account ID with a UNIQUE index and foreign key to the accounts table, the hash with a UNIQUE index and a timestamp.

In the page that creates the link, do not allow "reset my password" based on information that can be obtained by a random person. If you do this, one can fill your table with reset password requests and generate spam and security concerns with your users.

In the page where the link is verified first delete all expired records by comparing NOW() with the stored timestamp, then simply SELECT using WHERE='$hash' (of course, you sanitize $hash). Given the UNIQUE index on the hash, this can only return one row or no rows.

The UNIQUE index on the account ID ensures that people cannot request multiple resets within the expiration time.