Let's say we want to new users to confirm their email address on a secure website (one that we don't want users making fake accounts impersonating other users). For UX reasons we may want:
- Short as possible codes in case user types it in
- alphanumeric codes for easy typing
- Does not require user to re-enter their email address when confirming the code
A code that is too short is vulnerable to brute force attempts to confirm it. For example the code 1234 could be easily guessed. The attacker just registers firstname.lastname@example.org and then spams verification codes until hitting the target (and may verify many other random emails).
There's a number of strategies to fight this including:
- Use a long code that can't be guessed - perhaps forcing the user to click a verify link instead of typing it in manually
- Expire code relatively quickly - giving the attacker less time
- Force the user to identify who they claim to be by either logging in or typing their email before the confirmation code. Then expire the code after X attempts. This forces the attacker to have to constantly restart their guessing - removing possibility for an exhaustive search. However it's potentially a UX papercut. Maybe a user clicks the confirm email on a phone after signing on with their desktop. The phone would require logging in and is a slight barrier to sign up.
- Make use of capcha, rate limiting, or other strategies to deter automation. This is probably not guaranteed to solve the issue alone.
Each strategy can potentially harm the UX however. What is a reasonable balance of UX without compromising security?