Email 2 step authentication (2fa) implementation - looking for feedback

Hello,

I am embarking on a quest to build a two step email authentication for my web app (there are good reasons not to use Google Authenticator).

I’m nearly there but I’d like to humbly ask the community for feedback on how to improve. I am not saying this is the right way, but’s how I’ve gotten it to work. So if you have any ideas on how to improve/make more secure, I’m all ears!

The idea is that a user inputs their credentials here:
image

Then, they get an email with an auth code to input here:
image

A few notes:

  • The emailed auth code has a 15 min expiration
  • There is a max 10 attempt login counter

On the login page the logic is as follows:

  1. Query to get login attempts for posted email
  2. Then, increment this number by 1
  3. If the count is less than 10, proceed to the first security provider and attempt to log in
  4. After login, set the 2fa token value, expiration date/time and update the DB
  5. Query the DB to get the user’s first name and send user an email with 2fa auth code

If login attempts > 10, send a 403 to the front end with a pretty error message and eventually email the user to let them know what happened to their account.

On the ‘enter auth code page’ the logic is as follows:

  1. To access this page, the user should have successfully logged into the prior page
  2. Query the user for posted email to get the 2fa expiration time and token value
  3. Update the number of login attempts
  4. If date/time is less than 15 minutes AND login count < 10, go to THEN condition
  5. Try to log the user in with the posted auth token
  6. Then reset the expiration time, token and login attempts

If the login count > 10, respond with a 403 status.

I’d love to get feedback and suggestions on how to improve.

1 Like

Hi @nepatriot. This looks like an excellent implementation. I’d like to follow this to try it in action.

One thought, and I’m not sure exactly how best to achieve it, is to somehow not divuldge if the username/password combination is correct or not before asking for the 2FA code. I like the idea of any attempts to log in are left blind whether they have the details correct or not rather than confirming when the username and password is correct as it means they know they’re half way there and can then concentrate on the 2FA part. But I might be being over paranoid!

You could maybe send them to the 2FA stage regardless of the success of the username/password and show a message saying something like ‘if the login details were correct then we’ve emailed your code to you’. But only actually email anything if the previous step was successful.

What do you think?

Also, how are you counting the 10 attempts? By username or IP address? I would do it by IP.

Why do you think it is not a good idea?

Whatever your reasons are it is still more secure than using 2fa email. Of all 2FA options there are I would say email is the worst. Followed closely by SMS.

2FA email isn’t really 2FA. The first factor you are trying to protect is something you know(the password) and the second factor is something “only” you have access to(email inbox).

The problem with email is that you only need to compromise one of those factors(email inbox) to get access to both as passwords are normally reset via email inbox. Therefore it’s a weak 2FA.

Actually one could argue it’s not a real 2FA if you allow password resets via email.

You may not like Google Authenticator app, but you can use other TOTP authentication software. Google doesn’t have dibs on the TOTP world :slight_smile:

4 Likes

Excellent point and one I’d not thought of.

I use Authy. It’s compatible with Google Authenticator but not actually anything to do with Google.

I’d be interested to hear your thinking on this, too.

1 Like

Thank you @sitestreet and @JonL for your feedback!

@sitestreet, great points about divulging the correct credentials. I’ve set this whole thing up that after 10 failed attempts, the account is locked. Also, to your last, I will adjust the logic to count login attempts by IP not user.

@JonL, great points about the pitfalls of email as 2FA. Given my comment below, picking a 2FA method is a bit more challenging but this is certainly something I’m going to think about and try to come up with a better long term solution.

My users are in Healthcare which is generally speaking 20 years behind in tech. By introducing a third party application into the mix (Google Auth/Authy), I would be introducing hurdles that would be difficult for users to deal with. It sounds crazy to techies, but some of these folks are the people for whom downloading an app at the app store is a daunting task.

2 Likes

Then sending an SMS is a better, more secure, option than email.

1 Like