jazzband / django-two-factor-auth

Complete Two-Factor Authentication for Django providing the easiest integration into most Django projects.
MIT License
1.69k stars 445 forks source link

Email Method, sends the email, then if i abandon the page view, it has enabled two factor authentication but I haven't completed the validation step #562

Open seen-it opened 2 years ago

seen-it commented 2 years ago

On the EmailMethod the validation step creates an EmailDevice (django-otp) which if I abandon the page view without entering my token seems to enable two factor authentication on that account, in a strange state too where i cannot disable the enabled 2fa on the account or finish the original setup for the account.

Probably should be able to finish an abandoned setup process if the user fails to enter the first validation token

The current behaviour is that if i select the email method, the web browser takes me straight to the validation step in which the user enters the token sent to the users email address, the user recieves that token but then abandons the session or closes the web page. Then if the user attempts to view the profile screen to rerun the not completed 2fa setup it shows the account as enabled, in which if the user tries to disable there account it just takes them back to to LOGIN_REDIRECT_URL

seems like the issue stems from here https://github.com/jazzband/django-two-factor-auth/blob/master/two_factor/views/core.py#L514 https://github.com/django-otp/django-otp/blob/master/src/django_otp/plugins/otp_email/models.py#L59

inellas commented 2 years ago

I have experienced the same problem. Do we have any update regarding this?

It seems quite important, as it may lead to a user being locked out of their account under certain circumstances:

  1. A user wants to enable two factor authentication by email and types a wrong email address by mistake.
  2. When clicking next, they realize that the token will never be received as they have entered a wrong email address. Now the two factor authentication looks enabled, without the email validation step and without being able to disable it.
  3. Even worse, if the user logs out and tries to log in again, they will never be able to do so, as the system will be asking for a token that is being sent to a wrong email address.
claudep commented 2 years ago

@Atterratio, @pickfire, @dchukhin, any idea for a fix?

pickfire commented 2 years ago

I don't use email for two factor, so not affected by this, but I didn't look closely into this and not really familiar with this part.

Maybe do a git bisect and see which commit caused the issue, then we can investigate from there?

pickfire commented 1 year ago

Ah, I tried using this and I noticed this problem. I took a look into this, my take is that confirmed should be disabled by default, and only once confirmed then it is confirmed, then only mark it as confirmed.

https://github.com/django-otp/django-otp/blob/ac020731cd30d5ef086a040fe256118be8196f69/src/django_otp/plugins/otp_email/migrations/0001_initial.py#L19

I tested it out by stopping halfway throughout the flow, manually set confirmed to False, then it still work.

Once we create the EmailDevice, set the confirmed to False, then once user confirmed the email, on complete we only set it to confirmed. Then the user should be won't have to loop into the login page and can go to the setup page again.

But I think somehow we should have some mechanisms to delete the email devices that are not confirmed.

milafrerichs commented 1 year ago

@pickfire any update on this? I ran into this a few days ago and then found this open issue.

thanks!

pickfire commented 1 year ago

I am not working on this. Feel free to send a PR to fix this issue. @milafrerichs