As I continue to build more and more websites and web applications I am often asked to store user's passwords in a way that they can be retrieved if/when the user has an issue (either to email a forgotten password link, walk them through over the phone, etc.) When I can I fight bitterly against this practice and I do a lot of ‘extra’ programming to make password resets and administrative assistance possible without storing their actual password.
When I can’t fight it (or can’t win) then I always encode the password in some way so that it, at least, isn’t stored as plaintext in the database—though I am aware that if my DB gets hacked it wouldn't take much for the culprit to crack the passwords, so that makes me uncomfortable.
In a perfect world folks would update passwords frequently and not duplicate them across many different sites—unfortunately I know MANY people that have the same work/home/email/bank password, and have even freely given it to me when they need assistance. I don’t want to be the one responsible for their financial demise if my DB security procedures fail for some reason.
Morally and ethically I feel responsible for protecting what can be, for some users, their livelihood even if they are treating it with much less respect. I am certain that there are many avenues to approach and arguments to be made for salting hashes and different encoding options, but is there a single ‘best practice’ when you have to store them? In almost all cases I am using PHP and MySQL if that makes any difference in the way I should handle the specifics.
Additional Information for Bounty
I want to clarify that I know this is not something you want to have to do and that in most cases refusal to do so is best. I am, however, not looking for a lecture on the merits of taking this approach I am looking for the best steps to take if you do take this approach.
In a note below I made the point that websites geared largely toward the elderly, mentally challenged, or very young can become confusing for people when they are asked to perform a secure password recovery routine. Though we may find it simple and mundane in those cases some users need the extra assistance of either having a service tech help them into the system or having it emailed/displayed directly to them.
In such systems the attrition rate from these demographics could hobble the application if users were not given this level of access assistance, so please answer with such a setup in mind.
Thanks to Everyone
This has been a fun question with lots of debate and I have enjoyed it. In the end I selected an answer that both retains password security (I will not have to keep plain text or recoverable passwords), but also makes it possible for the user base I specified to log into a system without the major drawbacks I have found from normal password recovery.
As always there were about 5 answers that I would like to have marked as correct for different reasons, but I had to choose the best one--all the rest got a +1. Thanks everyone!
Also, thanks to everyone in the Stack community who voted for this question and/or marked it as a favorite. I take hitting 100 up votes as a compliment and hope that this discussion has helped someone else with the same concern that I had.
Handling lost/forgotten passwords:
Nobody should ever be able to recover passwords.
If users forgot their passwords, they must at least know their user names or email addresses. Upon request, generate a GUID in the Users table and sent an email containing a link containing the guid as a parameter to the user's email address.
The page behind the link verifies that the parameter guid really exists (probably with some timeout logic), and asks the user for a new password.
If you need to have hotline help users, add some roles to your grants model and allow the hotline role to temporarily login as identified user. Log all such hotline logins. For example, Bugzilla offers such an impersonation feature to admins.
Another option you may not have considered is allowing actions via email. It is a bit cumbersome, but I implemented this for a client that needed users "outside" their system to view (read only) certain parts of the system. For example:
As you mentioned in the comments, this won't work if the email is compromised, but it does address @joachim 's comment about not wanting to reset the password. Eventually, they would have to use the password reset, but they could do that at a more convenient time, or with assistance of an administrator or friend, as needed.
A twist to this solution would be to send the action request to a third party trusted administrator. This would work best in cases with the elderly, mentally challenged, very young or otherwise confused users. Of course this requires a trusted administrator for these people to support their actions.