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):
- Saving the email
- The user clicks the "I forgot my password" link on the login page
- A Modal appears prompting for email
- Using an AJAX call, the email is saved in the database in a queue table without verification, etc.
- Sending the mail
- 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)
- A unique id is saved in a different db table with the associated email address
- An email is sent to the email with the link as part of the URL
- (Another cleanup job removes these entries from the table if they are more than X hours old)
- Using the link
- The user clicks the link in the mail.
- 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.
- 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.
- 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?
eg:
base64encode('S0M3Ey3Dee'+':'+'[email protected]')
-> https://mysite.com/recoverPassword/UzBNM0V5M0RlZTpzb21lQGVtYWlsLmNvbQ
)
or
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)
Clarification
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.