Email verification is good enough for most applications
It may not be perfect but most people expect and accept this kind of approach. Overall, a good process is as follows
- User clicks "Forgot password"
- System generates a one-time token (UUID), stores it in the database marking it as new
- Email containing a HTTPS password reset link with the UUID sent to user email account. This is the weakness because it assumes that the user is authorised by their access to their email account, not the secret information you previously shared.
- User clicks the link and the system verifies that the UUID is unused
- Assuming all is well, the user is taken through the password reset process, which first marks the UUID as used and then accepts password updates.
- The password is salted and hashed and then stored in the database. The plaintext version of the password is never persisted. Ever.
If the data you are trying to protect is much more valuable (tax returns, bank details etc) then you need a stricter implicit authorisation process (see step 3 previously). This is usually in the form of a letter containing the UUID (usually hidden within a tamperproof envelope). The user is then expected to activate the password reset process and manually enter the UUID.
Finally, if the above is not enough then you're into the realms of identity management. You'll be breaking out the proof of address, driving license, passport, birth certificate, personal references and all the other frippery necessary to establish beyond reasonable doubt that the user is who they say they are. And then you proceed to step 5.