What is the suggested best practice for changing a user's email address?
The problem I see with confirming the old email address is that sometimes people change address because they cannot access the old one anymore. For example, the old address might have expired (and maybe even reassigned to someone else!). Or they might just have forgotten the password to the old address, and have no alternative ways to prove their identity. Or the old address belonged to a company where they used to work, and they don't have access to it anymore. Or it might have been blocked or terminated for for other reasons (violation of ToS, DoSed, filled with spam and practically unusable, etc.)
So the way I see it, you have two ways to log in to an account: using your password, or using your email account to request a password reset. Therefore the email account is an alternative way to authenticate. Now, whenever you make changes to the ways you can authenticate, you should verify your identity. And if you can't rely on the old email account (that you are about to change) the obvious solution seems to ask for your current password before you can change the address.
- Ask for your current password (it's a valid verification of your identity) to be able to change the email address.
- Verify you have access to the new email address and, if verified, make it the new default one.
- Maybe do something with the old address that has been changed.
What you do with the old account, in my opinion, has some pros and cons. You could decide to:
- Send a notice to the old email, for example: "Your email address for accessing Website Example has been changed, if you didn't expect this your account might have been compromised, etc." You might also provide a link to recover the possibly compromised account, with a token that expires after some time. The problem with this option is that if the old account has been reassigned to someone else, you would not want to let them know too much information (and definitely not give them a direct recovery option)
- Just throw away the old email once it's been successfully updated, without sending any notices. The problem with this is that if an attacker manages to steal a user's password, they can take over their account completely and lock them out.
- Don't send anything to the old email, but keep it in the database for some time, for support or recovery, in case the real owner of a compromised account (with the old email) shows up asking for help. The problem with this option is that the real owner, in case the account is compromised, might not realize it until... how long?
- Confirmation of new email
What I feel like the method used by most platforms: You will receive a confirmation email to the new address you provide. This will assure you typed in the e-mail correctly, will not stop anyone from changing the main login method though.
This should be the 'correct' way. Rationale:
- this confirms that the mail address you entered was correct and free of typos
- that you have access to it
- and that the mailserver hosting it is reachable and will accept the mail - there could be a DNS misconfiguration, or a spam filter preventing mail delivery
So the change of mail address should not be carried out until it is confirmed.
There is one problem with this method: if you were logged in on a computer that is left unattended, someone else could change the mail address and take over your user account.
The solution is to confirm the request with the current password. That's one more step but I feel that the inconvenience is tolerable: users should not change their registered mail address often.
Variant: you can ask for an answer to a secret question if your site has that option at signup. Preferably not a secret question like birth date which is probably public knowledge...
Rationale: it is possible that your password was compromised and found in some pwnlist, especially if you reuse the same password across sites. But there is a chance that the answer to your secret questions will not be found easily. The downside: the questions and answers previously recorded should then not be visible or modifiable anymore. That means you should be using questions that have stable/permanent answers while avoiding the trap of common, not-so-secret questions like the birth date or mother's maiden name.
So maybe this is an option that is practical for some sites but not all of them.
- Confirmation through old address
Very few platforms send an email to the old address to check if I am the actual owner of this account. If I click the link in the mail or enter a number they send me, the adress is changed.
As hinted earlier, the user may have lost control of the old address, it may be a professional address from a business you left (or were fired from). Or the address could have lapsed or been allocated to someone else. There is a risk of unwanted information disclosure here. Once you've confirmed the new address the previous one should not be used anymore.
Last but not least: log all changes made to the user profile. If someone reports unauthorized access you should be able to tell when the change was made and the IP address that initiated the change. Actually, the confirmation mail will often include the IP address. Clarify this in your privacy policy: what kind of information you record, when and for how long while ensuring compliance with applicable regulations.
If your site has 2FA and the user has it enabled, 2FA confirmation would be desirable, depending on the nature of the service. If you just want to change the mail address for some free newsletter subscription - 2FA is not justified. If you're a bank, it's different. SMS/OTP will probably come into play.
If you consider email as a form of verification of account identify then ideally you should be looking to confirm any changes via an alternative form, for example sms, other email account, soft token, physical letter etc.
In many cases email is the primary id for your account and depending on how secure the account is you will need increasing forms of alternative validation.
- Example 1 in your question is totally insecure and flawed on many levels
- Example 2 is still insecure as the malicious actor only needs to confirm the change on the email service they control (no original email factor validation)
- Example 3 should be the minimum, however additional validation/verification factors should be employed if the account is aiming to be secure
- Example 4 is not really any more secure than 3 and only really aids in making sure the new email is valid
Best practice should be to validate on alternative communication factors. How many and what type depend on the service and the risk appetite of the vendor.