Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only validate token against chosen device (#473) #521

Closed
wants to merge 3 commits into from

Conversation

Gautier
Copy link
Contributor

@Gautier Gautier commented Jul 26, 2022

Description

Changes the AuthenticationTokenForm to only validate a token against the chosen device.

The first version of this PR only includes a failing test to demonstrate the problem and the second version is a suggestion on how to fix it.

Motivation and Context

I received the same error report as #473 for one of my system using django-two-factor-auth and noticed the backup tokens throttling_failure_count were being incremented even though the phone TOTP worked.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project. (no black?)
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@Gautier Gautier changed the title Demonstrate #473 - Valid backup authentication codes don't log user Only validate token against chosen device (#473) Jul 27, 2022
@Gautier Gautier force-pushed the master branch 2 times, most recently from 954522d to 08daca8 Compare August 1, 2022 10:49
Copy link
Collaborator

@moggers87 moggers87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some comments/questions after a quick read through

except ObjectDoesNotExist:
raise forms.ValidationError(self.error_messages['invalid_device_id'])

def _chosen_device(self, user):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method doesn't appear to be called by anything, what's it for?

Copy link
Contributor Author

@Gautier Gautier Sep 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_chosen_device is the method called by the OTPTokenForm._clean_otp method in django-otp.

It currently returns None which makes django-otp try to match the token against each user's devices in order until one works (in match_token) but since match_token uses devices_for_token which iterates over the devices that way for model in device_classes(): there is no guarantee that it won't try the backup devices first.

I have added more details in my comment at the related issue at : #473 (comment) under the heading "Full investigation".

def clean_device_id(self):
if self.data.get("device_id"):
try:
for user_device in devices_for_user(self.user):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that we know the device ID, couldn't we just fetch it directly rather than iterating over all devices like this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I have updated the PR to use Device.from_persistent_id instead.

be verified against all devices, it is not limited to the given
device.
`initial_device` is either the user's default device a backup device
when the user chooses to enter a backup token.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand this new comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated the comment to include the crucial missing word "or" in "default device or a backup device"

@milafrerichs
Copy link

Any updates on this? We ran into this issue as well. Would be great to have a fix on the main package.
Can I help in any way?

@PetrDlouhy
Copy link
Contributor

@moggers87 @Gautier What is state of this PR? Could I help somehow?

@claudep
Copy link
Contributor

claudep commented Dec 12, 2023

Rebasing looks like the next step, then @PetrDlouhy, your review would be welcome, too!

@PetrDlouhy
Copy link
Contributor

@claudep I have rebased this in PR #683, all tests are passing now.

@PetrDlouhy
Copy link
Contributor

I have tried to rebase this in #683, but I am not able to resolve the review comments there without much deeper investigation.

@Gautier Would you be able to look at it?
I am a bit confused, because I tried to run the tests.test_views_login.LoginTest.test_totp_token_does_not_impact_backup_token test with the unfixed forms.py code and it seems to pass.

I will try to give it more time, but it would save me some nerves if you could look at it.

@PetrDlouhy
Copy link
Contributor

I did investigate it a bit more and I realized that in the new version of django-two-factor-auth there is AuthenticationTokenForm._chosen_device() newly implemented.
I am not yet sure if that is enough to fix #473 or there is some case in which it could still fail.

@PetrDlouhy
Copy link
Contributor

The relevant test from this PR is merged now and is passing because of other fixes in the current branch.

Other changes included in this PR are probably not needed and if they are, they would need a clear test case first.
I am closing this, open new PR in such cases.

@PetrDlouhy PetrDlouhy closed this Jan 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants