You're right to be thinking about security here — password reset flows are critical attack vectors if not handled correctly. Let's walk through the issue and how to solve it.
Don't Reveal Whether an Email Exists
Most modern applications implement the "silent fail" approach:
Always show a generic message like:
"If an account with that email exists, we’ve sent a password reset link."
Behind the scenes, you only send a reset email if the user exists — otherwise, do nothing.
This prevents email enumeration attacks, where an attacker could test emails and learn which ones are registered.
Reset Link Should Be Secure and Tied to the User
When sending a reset link:
Generate a secure, time-limited token (usually with UserManager.GeneratePasswordResetTokenAsync()
in ASP.NET Core Identity).
Store it securely and tie it to the correct user account.
Send a link like:
When the user clicks the link, verify the token and email match, using:
await UserManager.ResetPasswordAsync(user, token, newPassword);
If the email doesn't exist, no reset token is generated — and no email is sent.