How long should a password reset token remain valid?

The answer depends really on the complexity of your reset token. The aim should be that a reset token is not guessable in the given valid time.

So for instance if your reset token is 5 characters long, only digits and your server is capable of answering to 100 requests per second without rate limiting, 15 minutes is likely too long. Just think about the possible attack:

  1. An attacker resets his own password to see how the links work
  2. The attacker resets the account of his victim, knowing he has n minutes time
  3. The attacker calls the password-reset page with more or less random keys until he finds the correct one.

This - especially step 3 - should not be possible in the given amount of time. That means if you have a great enough universe to draw reset-keys from (like 32 chars, alphanumeric) as well as rate limiting in your application, even one day won't affect your security much. Also you can (and should) choose to inform your user with a second email/message on the performed password change. Also note that your application may support very long reset-tokens without compromising the user experience as they never have to type it.

Edit: Of course you should calculate in a way that only a very small percentage of keys can be tested in the given amount of time. For example a 0.000001% chance of guessing the right key in the given timeslot might be an acceptable risk. A small amount of risk is something that you will have to accept in any way.