diff --git a/requirements/base.in b/requirements/base.in index df9c8322..ea7ea985 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -13,8 +13,7 @@ django-axes django-jsonsuit django-redis django-rosetta -maykin-django-two-factor-auth -maykin-django-two-factor-auth[phonenumbers] +maykin-2fa mozilla-django-oidc-db sharing-configs diff --git a/requirements/base.txt b/requirements/base.txt index d5cbd282..71967b9d 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -8,6 +8,8 @@ amqp==5.1.1 # via kombu asgiref==3.6.0 # via django +asn1crypto==1.5.1 + # via webauthn async-timeout==4.0.2 # via redis attrs==23.1.0 @@ -20,6 +22,8 @@ boltons==23.0.0 # via # face # glom +cbor2==5.6.1 + # via webauthn celery==5.2.7 # via notifications-api-common certifi==2023.5.7 @@ -50,12 +54,13 @@ coreapi==2.3.3 # via commonground-api-common coreschema==0.0.4 # via coreapi -cryptography==40.0.2 +cryptography==42.0.2 # via # django-simple-certmanager # josepy # mozilla-django-oidc # pyopenssl + # webauthn django==3.2.20 # via # -r requirements/base.in @@ -75,11 +80,12 @@ django==3.2.20 # django-rosetta # django-simple-certmanager # django-solo + # django-two-factor-auth # djangorestframework # drf-nested-routers # drf-spectacular # drf-yasg - # maykin-django-two-factor-auth + # maykin-2fa # mozilla-django-oidc # mozilla-django-oidc-db # notifications-api-common @@ -94,7 +100,7 @@ django-filter==23.2 # -r requirements/base.in # commonground-api-common django-formtools==2.4.1 - # via maykin-django-two-factor-auth + # via django-two-factor-auth django-ipware==6.0.3 # via django-axes django-jsonform==2.21.5 @@ -104,9 +110,9 @@ django-jsonsuit==0.5.0 django-ordered-model==3.7.4 # via django-admin-index django-otp==1.2.0 - # via maykin-django-two-factor-auth + # via django-two-factor-auth django-phonenumber-field==5.2.0 - # via maykin-django-two-factor-auth + # via django-two-factor-auth django-privates==2.0.0.post0 # via django-simple-certmanager django-redis==5.2.0 @@ -128,6 +134,8 @@ django-solo==2.0.0 # notifications-api-common # sharing-configs # zgw-consumers +django-two-factor-auth[phonenumberslite,webauthn]==1.16.0 + # via maykin-2fa djangorestframework==3.12.4 # via # -r requirements/base.in @@ -185,7 +193,7 @@ kombu==5.2.4 # via celery markupsafe==2.1.2 # via jinja2 -maykin-django-two-factor-auth[phonenumbers]==2.0.4 +maykin-2fa==1.0.0 # via -r requirements/base.in mozilla-django-oidc==4.0.0 # via mozilla-django-oidc-db @@ -197,8 +205,8 @@ oyaml==1.0 # via commonground-api-common packaging==23.1 # via drf-yasg -phonenumbers==8.13.11 - # via maykin-django-two-factor-auth +phonenumberslite==8.13.30 + # via django-two-factor-auth pillow==9.5.0 # via -r requirements/base.in polib==1.2.0 @@ -213,10 +221,11 @@ pyjwt==2.7.0 # via # commonground-api-common # gemma-zds-client -pyopenssl==23.1.1 +pyopenssl==24.0.0 # via # django-simple-certmanager # josepy + # webauthn # zgw-consumers pyrsistent==0.19.3 # via jsonschema @@ -244,7 +253,7 @@ pyyaml==6.0 # gemma-zds-client # oyaml qrcode==6.1 - # via maykin-django-two-factor-auth + # via django-two-factor-auth redis==4.5.5 # via django-redis requests==2.31.0 @@ -291,6 +300,8 @@ vine==5.0.0 # kombu wcwidth==0.2.6 # via prompt-toolkit +webauthn==2.0.0 + # via django-two-factor-auth wrapt==1.15.0 # via elastic-apm zgw-consumers==0.26.1 diff --git a/requirements/ci.txt b/requirements/ci.txt index c47c56fa..0aceecbf 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -12,6 +12,10 @@ asgiref==3.6.0 # via # -r requirements/base.txt # django +asn1crypto==1.5.1 + # via + # -r requirements/base.txt + # webauthn async-timeout==4.0.2 # via # -r requirements/base.txt @@ -32,6 +36,10 @@ boltons==23.0.0 # -r requirements/base.txt # face # glom +cbor2==5.6.1 + # via + # -r requirements/base.txt + # webauthn celery==5.2.7 # via # -r requirements/base.txt @@ -82,13 +90,14 @@ coreschema==0.0.4 # coreapi coverage==4.5.4 # via -r requirements/test-tools.in -cryptography==40.0.2 +cryptography==42.0.2 # via # -r requirements/base.txt # django-simple-certmanager # josepy # mozilla-django-oidc # pyopenssl + # webauthn cssselect==1.2.0 # via pyquery django==3.2.20 @@ -112,11 +121,12 @@ django==3.2.20 # django-sendfile2 # django-simple-certmanager # django-solo + # django-two-factor-auth # djangorestframework # drf-nested-routers # drf-spectacular # drf-yasg - # maykin-django-two-factor-auth + # maykin-2fa # mozilla-django-oidc # mozilla-django-oidc-db # notifications-api-common @@ -133,7 +143,7 @@ django-filter==23.2 django-formtools==2.4.1 # via # -r requirements/base.txt - # maykin-django-two-factor-auth + # django-two-factor-auth django-ipware==6.0.3 # via # -r requirements/base.txt @@ -153,11 +163,11 @@ django-ordered-model==3.7.4 django-otp==1.2.0 # via # -r requirements/base.txt - # maykin-django-two-factor-auth + # django-two-factor-auth django-phonenumber-field==5.2.0 # via # -r requirements/base.txt - # maykin-django-two-factor-auth + # django-two-factor-auth django-privates==2.0.0.post0 # via # -r requirements/base.txt @@ -190,6 +200,10 @@ django-solo==2.0.0 # notifications-api-common # sharing-configs # zgw-consumers +django-two-factor-auth[phonenumberslite,webauthn]==1.16.0 + # via + # -r requirements/base.txt + # maykin-2fa django-webtest==1.9.10 # via -r requirements/test-tools.in djangorestframework==3.12.4 @@ -283,7 +297,7 @@ markupsafe==2.1.2 # via # -r requirements/base.txt # jinja2 -maykin-django-two-factor-auth[phonenumbers]==2.0.4 +maykin-2fa==1.0.0 # via -r requirements/base.txt mozilla-django-oidc==4.0.0 # via @@ -303,10 +317,10 @@ packaging==23.1 # via # -r requirements/base.txt # drf-yasg -phonenumbers==8.13.11 +phonenumberslite==8.13.30 # via # -r requirements/base.txt - # maykin-django-two-factor-auth + # django-two-factor-auth pillow==9.5.0 # via -r requirements/base.txt polib==1.2.0 @@ -328,11 +342,12 @@ pyjwt==2.7.0 # -r requirements/base.txt # commonground-api-common # gemma-zds-client -pyopenssl==23.1.1 +pyopenssl==24.0.0 # via # -r requirements/base.txt # django-simple-certmanager # josepy + # webauthn # zgw-consumers pyquery==2.0.0 # via -r requirements/test-tools.in @@ -371,7 +386,7 @@ pyyaml==6.0 qrcode==6.1 # via # -r requirements/base.txt - # maykin-django-two-factor-auth + # django-two-factor-auth redis==4.5.5 # via # -r requirements/base.txt @@ -438,6 +453,10 @@ wcwidth==0.2.6 # via # -r requirements/base.txt # prompt-toolkit +webauthn==2.0.0 + # via + # -r requirements/base.txt + # django-two-factor-auth webob==1.8.7 # via webtest webtest==3.0.0 diff --git a/requirements/dev.txt b/requirements/dev.txt index e08479af..82b0870f 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -14,6 +14,10 @@ asgiref==3.6.0 # via # -r requirements/ci.txt # django +asn1crypto==1.5.1 + # via + # -r requirements/ci.txt + # webauthn async-timeout==4.0.2 # via # -r requirements/ci.txt @@ -46,6 +50,10 @@ bump2version==1.0.1 # via bumpversion bumpversion==0.6.0 # via -r requirements/dev.in +cbor2==5.6.1 + # via + # -r requirements/ci.txt + # webauthn celery==5.2.7 # via # -r requirements/ci.txt @@ -98,13 +106,14 @@ coreschema==0.0.4 # coreapi coverage==4.5.4 # via -r requirements/ci.txt -cryptography==40.0.2 +cryptography==42.0.2 # via # -r requirements/ci.txt # django-simple-certmanager # josepy # mozilla-django-oidc # pyopenssl + # webauthn cssselect==1.2.0 # via # -r requirements/ci.txt @@ -132,11 +141,12 @@ django==3.2.20 # django-sendfile2 # django-simple-certmanager # django-solo + # django-two-factor-auth # djangorestframework # drf-nested-routers # drf-spectacular # drf-yasg - # maykin-django-two-factor-auth + # maykin-2fa # mozilla-django-oidc # mozilla-django-oidc-db # notifications-api-common @@ -157,7 +167,7 @@ django-filter==23.2 django-formtools==2.4.1 # via # -r requirements/ci.txt - # maykin-django-two-factor-auth + # django-two-factor-auth django-ipware==6.0.3 # via # -r requirements/ci.txt @@ -177,11 +187,11 @@ django-ordered-model==3.7.4 django-otp==1.2.0 # via # -r requirements/ci.txt - # maykin-django-two-factor-auth + # django-two-factor-auth django-phonenumber-field==5.2.0 # via # -r requirements/ci.txt - # maykin-django-two-factor-auth + # django-two-factor-auth django-privates==2.0.0.post0 # via # -r requirements/ci.txt @@ -214,6 +224,10 @@ django-solo==2.0.0 # notifications-api-common # sharing-configs # zgw-consumers +django-two-factor-auth[phonenumberslite,webauthn]==1.16.0 + # via + # -r requirements/ci.txt + # maykin-2fa django-webtest==1.9.10 # via -r requirements/ci.txt djangorestframework==3.12.4 @@ -320,7 +334,7 @@ markupsafe==2.1.2 # via # -r requirements/ci.txt # jinja2 -maykin-django-two-factor-auth[phonenumbers]==2.0.4 +maykin-2fa==1.0.0 # via -r requirements/ci.txt mccabe==0.7.0 # via flake8 @@ -349,10 +363,10 @@ packaging==23.1 # sphinx pathspec==0.11.1 # via black -phonenumbers==8.13.11 +phonenumberslite==8.13.30 # via # -r requirements/ci.txt - # maykin-django-two-factor-auth + # django-two-factor-auth pillow==9.5.0 # via -r requirements/ci.txt pip-tools==6.13.0 @@ -384,11 +398,12 @@ pyjwt==2.7.0 # -r requirements/ci.txt # commonground-api-common # gemma-zds-client -pyopenssl==23.1.1 +pyopenssl==24.0.0 # via # -r requirements/ci.txt # django-simple-certmanager # josepy + # webauthn # zgw-consumers pyproject-hooks==1.0.0 # via build @@ -429,7 +444,7 @@ pyyaml==6.0 qrcode==6.1 # via # -r requirements/ci.txt - # maykin-django-two-factor-auth + # django-two-factor-auth redis==4.5.5 # via # -r requirements/ci.txt @@ -528,6 +543,10 @@ wcwidth==0.2.6 # via # -r requirements/ci.txt # prompt-toolkit +webauthn==2.0.0 + # via + # -r requirements/ci.txt + # django-two-factor-auth webob==1.8.7 # via # -r requirements/ci.txt diff --git a/src/objecttypes/conf/base.py b/src/objecttypes/conf/base.py index 3a4443c3..e74b4586 100644 --- a/src/objecttypes/conf/base.py +++ b/src/objecttypes/conf/base.py @@ -75,11 +75,12 @@ "solo", "drf_spectacular", "vng_api_common", - # 2fa apps + # Two-factor authentication in the Django admin, enforced. "django_otp", "django_otp.plugins.otp_static", "django_otp.plugins.otp_totp", "two_factor", + "maykin_2fa", "sharing_configs", # Project applications. "objecttypes.accounts", @@ -96,11 +97,11 @@ "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", + "maykin_2fa.middleware.OTPMiddleware", "mozilla_django_oidc_db.middleware.SessionRefresh", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", "axes.middleware.AxesMiddleware", - "django_otp.middleware.OTPMiddleware", ] ROOT_URLCONF = "objecttypes.urls" @@ -395,10 +396,18 @@ # -# Maykin fork of DJANGO-TWO-FACTOR-AUTH +# MAYKIN-2FA +# Uses django-two-factor-auth under the hood, so relevant upstream package settings +# apply too. # -TWO_FACTOR_FORCE_OTP_ADMIN = config("TWO_FACTOR_FORCE_OTP_ADMIN", not DEBUG) -TWO_FACTOR_PATCH_ADMIN = config("TWO_FACTOR_PATCH_ADMIN", True) + +# we run the admin site monkeypatch instead. +TWO_FACTOR_PATCH_ADMIN = False +# add entries from AUTHENTICATION_BACKENDS that already enforce their own two-factor +# auth, avoiding having some set up MFA again in the project. +MAYKIN_2FA_ALLOW_MFA_BYPASS_BACKENDS = [ + "mozilla_django_oidc_db.backends.OIDCAuthenticationBackend", +] # # Mozilla Django OIDC DB settings diff --git a/src/objecttypes/conf/ci.py b/src/objecttypes/conf/ci.py index 756a6fe1..e8c8c3ff 100644 --- a/src/objecttypes/conf/ci.py +++ b/src/objecttypes/conf/ci.py @@ -25,6 +25,3 @@ # Django-axes # AXES_BEHIND_REVERSE_PROXY = False - -# Maykin fork of DJANGO-TWO-FACTOR-AUTH -TWO_FACTOR_FORCE_OTP_ADMIN = False diff --git a/src/objecttypes/conf/dev.py b/src/objecttypes/conf/dev.py index c2e0000c..a467ddab 100644 --- a/src/objecttypes/conf/dev.py +++ b/src/objecttypes/conf/dev.py @@ -107,8 +107,9 @@ r"django\.db\.models\.fields", ) -if "test" in sys.argv: - TWO_FACTOR_FORCE_OTP_ADMIN = False +# None of the authentication backends require two-factor authentication. +if config("DISABLE_2FA", default=True): # pragma: no cover + MAYKIN_2FA_ALLOW_MFA_BYPASS_BACKENDS = AUTHENTICATION_BACKENDS # Override settings with local settings. try: diff --git a/src/objecttypes/templates/admin/base_site.html b/src/objecttypes/templates/admin/base_site.html index 45d313da..d8df6af0 100644 --- a/src/objecttypes/templates/admin/base_site.html +++ b/src/objecttypes/templates/admin/base_site.html @@ -23,9 +23,9 @@