I am currently implementing new auth schemes for a site, and decided to implement an "I forgot my password" email looking at this guide for inspiration.

My Flow

The flow I have designed is as follows (three phases):

  1. Saving the email
    1. The user clicks the "I forgot my password" link on the login page
    2. A Modal appears prompting for email
    3. Using an AJAX call, the email is saved in the database in a queue table without verification, etc.
  2. Sending the mail
    1. A scheduled job runs every ~10 seconds and picks up new entries in the queue. Entries where the email does not match a user are marked "failed" with "email not found" in the database, no interface is being built to show these anywhere. ( - I might remove all old entries every month as a cleanup measure)
    2. A unique id is saved in a different db table with the associated email address
    3. An email is sent to the email with the link as part of the URL
    4. (Another cleanup job removes these entries from the table if they are more than X hours old)
  3. Using the link
    1. The user clicks the link in the mail.
    2. The target page looks up the link in the database, and if it exists; the link is marked as fetched, an the page prompts for a new password twice.
    3. When the user clicks save, the email is retrieved from the database, and the user is retrieved, and the password token gets a new salt generated, and the new salt and password is saved.
    4. The reset link is deleted from the db

My question

Should I add the email address to the recoveryID to verify both pieces of data in my db?

base64encode('S0M3Ey3Dee'+':'+'[email protected]') -> https://mysite.com/recoverPassword/UzBNM0V5M0RlZTpzb21lQGVtYWlsLmNvbQ)
base64encode('[email protected]') -> https://mysite.com/recoverPassword/S0M3Ey3Dee:c29tZUBlbWFpbC5jb20

or just use the ID: https://mysite.com/recoverPassword/S0M3Ey3Dee

As I see it, an attacker already knows the email, which is attached top a real user, so the ID alone should be sufficient. I am just sitting with a feeling of this being potentially unsafe. But the only things I can think of doing is either ask users to supply a recovery secret like 'what was the color of your favourite pet' and ask for that as well, or to enforce 2FA, which is overkill for this application. (2FA may become a requirement for admins of the site)


The system is not high-risk, but does contain GDPR related information, but I'd prefer that uninvited guests don't just get a free entry.

Some (or most) users will most likely only visit the site once or twice after creating a login, so asking for too mush information wll deteriorate the user experience.

Edit: extra Clarification

My biggest worry was that a hacker would be able to brute force the Ids, but they would be only able to change the password for an account for which they know nothing, and use the one-time token. Adding the email as a prerequisite to the page would actually provide them with an extra piece of information.

1 Answer 1


Your workflow obeys the best practices rules:

  • do not warn if a user presents a non existant user id (here the mail address)
  • send a message on an already known alternative channel (here the mail) with a reset password link
  • on reception of that link, input the new password (twice to avoid possible typos) and store it in the password database
  • cleanup the password request list after a definite time (here few hours)

Other parts are just implementation details, but I would like to comment on one of them: you use a scheduled job running every 5 minutes to send the mails. IMHO, this will provide a poor user experience because 5 minutes for receiving a mail is rather long... I would prefere to immediately send the mail and prevent another mail to be sent again for 5 minutes.

Now for your question:

IMHO, passing the email in the link only makes sense if there is a risk to generate the same link for 2 different emails. As those links should contain unpredictible random data, it could be possible depending on other implementation details. But I would rather use a shorter deduplication key (for example a simple numeric sequence) and a longer random id. Or, as you need a database table indexed by that pseudo random id and giving the associated user id, along with the time at which it was generated, just rely on the database engine to ensure that those ids are unique.

  • I agree 5 minutes is long, I am most likely going to reduce it to 10 seconds. I was worried about a hacker being able to brute force the Ids, but if I don't recquire the email that is no issue, because they don't get the email or the user when they change the password.
    – JoSSte
    May 26, 2022 at 11:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .