Могу описать реализацию на одном из наших проектов:
1) пользователь вводит email;
1.1) проверяем существование данного аккаунта;
2) на почту отсылаем линк с уникальным сгенерированным идентификатором (который привязан к аккаунту), кликнув по которому, пользователь попадет на страницу с 2 полями для ввода — новый пароль и подтверждение.
3) при сабмите формы — записываем хеш нового пароля в поле временного пароля и отсылаем на почту пользователя ссылку для подтверждения данной операции (смену пароля).
4) у ссылки есть «время жизни» (у нас 6 часов) — если пользователь за это время перешел по ссылке, заменяем хеш пароля на новый и, вуаля, у пользователя новый пароль.