From 87564edc91a43c7143f8e94caf9ef1a6305fe4e3 Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Fri, 2 Feb 2024 09:46:40 +0100 Subject: [PATCH] :sparkles: Support WebAuthn 2.0 WebAuthn 2.0 refactored pydantic usage out of the codebase. For simplicity's sake, the minimum version is now set to 2.0 so that no compat layer is required. It appears that wat used to be Pydantic validation errors are now raised as InvalidJSONStructure exceptions, the form validation code is updated to reflect that. --- setup.py | 2 +- tox.ini | 2 +- two_factor/plugins/webauthn/forms.py | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index a7ba3e8f8..921445af8 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ extras_require={ 'call': ['twilio>=6.0'], 'sms': ['twilio>=6.0'], - 'webauthn': ['webauthn>=1.11.0,<1.99'], + 'webauthn': ['webauthn>=2.0,<2.99'], 'yubikey': ['django-otp-yubikey'], 'phonenumbers': ['phonenumbers>=7.0.9,<8.99'], 'phonenumberslite': ['phonenumberslite>=7.0.9,<8.99'], diff --git a/tox.ini b/tox.ini index b6abdf99c..37e2d69fa 100644 --- a/tox.ini +++ b/tox.ini @@ -45,7 +45,7 @@ deps = dj42: Django<5.0 djmain: https://github.com/django/django/archive/main.tar.gz yubikey: django-otp-yubikey - webauthn: webauthn>=1.2.1,<1.99 + webauthn: webauthn>=2.0,<2.99 webauthn: -rrequirements_e2e.txt coverage freezegun diff --git a/two_factor/plugins/webauthn/forms.py b/two_factor/plugins/webauthn/forms.py index 405558fb9..752d013d2 100644 --- a/two_factor/plugins/webauthn/forms.py +++ b/two_factor/plugins/webauthn/forms.py @@ -6,9 +6,9 @@ from django.utils import timezone from django.utils.module_loading import import_string from django.utils.translation import gettext_lazy as _ -from pydantic import ValidationError as PydanticValidationError from webauthn.helpers.exceptions import ( - InvalidAuthenticationResponse, InvalidRegistrationResponse, + InvalidAuthenticationResponse, InvalidJSONStructure, + InvalidRegistrationResponse, ) from webauthn.helpers.parse_authentication_credential_json import ( parse_authentication_credential_json, @@ -91,7 +91,7 @@ def _verify_token(self, user, token, device=None): new_sign_count = verify_authentication_response( device.public_key, device.sign_count, self.webauthn_rp, self.webauthn_origin, challenge, token) - except (PydanticValidationError, WebauthnDevice.DoesNotExist, InvalidAuthenticationResponse) as exc: + except (InvalidJSONStructure, WebauthnDevice.DoesNotExist, InvalidAuthenticationResponse) as exc: raise forms.ValidationError(_('Entered token is not valid.'), code='invalid_token') from exc device.sign_count = new_sign_count @@ -136,7 +136,7 @@ def clean_token(self): try: parse_registration_credential_json(token) - except InvalidRegistrationResponse as exc: + except (InvalidJSONStructure, InvalidRegistrationResponse) as exc: raise forms.ValidationError(_('Entered token is not valid.'), code='invalid_token') from exc self.cleaned_data = {