2

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 target@example.com 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?

  • 2
    Why not just use a token in the url link the email contains? One that ids the user and authenticates the request, that way it is all automatic? No need for codes etc. – Trickycm Sep 16 '17 at 14:32
  • I think the token with email link is a pretty good solution. But it removes the ability to just view the confirmation code in email and type it in. I imagine some situation where a user see the code fly up in a notification on their phone and just types it in on their desktop. That said this may still be the best UX possible. I might be over thinking possible papercuts when signing up. That said I see a lot of short codes out in the wild. – Bufke Sep 16 '17 at 14:42
  • 1
    @Bufke: if the user is entering the code within the same session as he created the user then you already have the identity belonging to the token and there is no need to ask for it again. An attacker would not only need to guess the token but also the session cookie. If the user is outside the session (maybe different browser) you can still ask for the claimed identity. – Steffen Ullrich Sep 16 '17 at 14:47
  • 3
    Provide a URL with a long identifier, user not having to login, and a short 4-digit code, where the user has to log in, and limit to for instance 5 attempts per 24hr. And it's not like it's hard to get an e-mail account today, so it's of limited overall value. – vidarlo Sep 16 '17 at 15:13
  • @vidarlo I like your answer a lot. It's slightly more development intensive having basically two systems to confirmation but really checks all the UX boxes. – Bufke Sep 16 '17 at 15:20
1

Provide a URL with a long identifier, user not having to login, and a short 4-digit code, where the user has to log in, and limit to for instance 5 attempts per 24hr.

And it's not like it's hard to get an e-mail account today, so it's of limited overall value.

  • Accepted this because it actually removes the need to ask "How long does it need to be". We can use a really large code for the email link and the short typed in code doesn't need to withstand brute force attempts. – Bufke Sep 17 '17 at 17:28
0

Put your necessary parameters like (user's email , request time , user ip , ...) in an array and add some random data as seed in your array. Then encrypt your array by AES-256 and add the output to your url.
Now just send the unique url to user email.
If the received data just decrypted successfully then you can validate the email address.

So your identification code is not vulnerable to bruteforce. Also you can add any other security parameters to url and implement extra security checks.

  • Exactly what does this add over generating a random number, and sending that - apart from being needlessly long? Noone's brute forcing a 128-bit number any day soon. – vidarlo Sep 16 '17 at 19:15
  • @vidarlo From a security viewpoint you're right. But from a programming viewpoint to make life easier you may want to pass the parameters through URL and don't use database for storing "random digit", "request time", etc. So you should secure the url parameters by something like AES-256. – ShayanKM Sep 16 '17 at 19:29
  • I'd say it would be more work to do this than to add a new table with two fields - user id and one time code... – vidarlo Sep 16 '17 at 20:21
0

I don't think having the user enter their e-mail is bad from a UX perspective. Many sites require the user to enter BOTH the code & e-mail, yet remain usable.

On registration, generate a secure hash and store it along the user's unique ID in a database.

Send them a link: "site.example/verify/$hash". On this page they will simply enter their e-mail, as that hash will never match up with another e-mail. Expire codes after a short interval, or if the account has been verified (which ever comes first).

Alternatively, you could require almost no user interaction if you like, this could be achieved by sending them: "site.example/verify/$hash/$mail" which may automatically fill the e-mail field.

To add onto this, you're probably best using a captcha/rate limiting as well. Even though a bot may never guess the hash (hopefully you choose a secure algo), it may cause application DOS by flooding your database with requests.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.