MFA remove improvement (#3239)

* temporary fix for GHSA-8j76-mm54-52xq

* return to setting afterwards
This commit is contained in:
Matthias Mair 2022-06-23 04:21:10 +02:00 committed by GitHub
parent 4268130669
commit 7283197bac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 5 deletions

View File

@ -15,6 +15,7 @@ from allauth.account.forms import SignupForm, set_form_field_order
from allauth.exceptions import ImmediateHttpResponse from allauth.exceptions import ImmediateHttpResponse
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
from allauth_2fa.adapter import OTPAdapter from allauth_2fa.adapter import OTPAdapter
from allauth_2fa.forms import TOTPDeviceRemoveForm
from allauth_2fa.utils import user_has_valid_totp_device from allauth_2fa.utils import user_has_valid_totp_device
from crispy_forms.bootstrap import (AppendedText, PrependedAppendedText, from crispy_forms.bootstrap import (AppendedText, PrependedAppendedText,
PrependedText) PrependedText)
@ -269,3 +270,36 @@ class CustomSocialAccountAdapter(RegistratonMixin, DefaultSocialAccountAdapter):
# Otherwise defer to the original allauth adapter. # Otherwise defer to the original allauth adapter.
return super().login(request, user) return super().login(request, user)
# Temporary fix for django-allauth-2fa # TODO remove
# See https://github.com/inventree/InvenTree/security/advisories/GHSA-8j76-mm54-52xq
class CustomTOTPDeviceRemoveForm(TOTPDeviceRemoveForm):
"""Custom Form to ensure a token is provided before removing MFA"""
# User must input a valid token so 2FA can be removed
token = forms.CharField(
label=_('Token'),
)
def __init__(self, user, **kwargs):
"""Add token field."""
super().__init__(user, **kwargs)
self.fields['token'].widget.attrs.update(
{
'autofocus': 'autofocus',
'autocomplete': 'off',
}
)
def clean_token(self):
"""Ensure at least one valid token is provided."""
# Ensure that the user has provided a valid token
token = self.cleaned_data.get('token')
# Verify that the user has provided a valid token
for device in self.user.totpdevice_set.filter(confirmed=True):
if device.verify_token(token):
return token
raise forms.ValidationError(_("The entered token is not valid"))

View File

@ -35,9 +35,9 @@ from .views import (AboutView, AppearanceSelectView, CurrencyRefreshView,
CustomConnectionsView, CustomEmailView, CustomConnectionsView, CustomEmailView,
CustomPasswordResetFromKeyView, CustomPasswordResetFromKeyView,
CustomSessionDeleteOtherView, CustomSessionDeleteView, CustomSessionDeleteOtherView, CustomSessionDeleteView,
DatabaseStatsView, DynamicJsView, EditUserView, IndexView, CustomTwoFactorRemove, DatabaseStatsView, DynamicJsView,
NotificationsView, SearchView, SetPasswordView, EditUserView, IndexView, NotificationsView, SearchView,
SettingsView, auth_request) SetPasswordView, SettingsView, auth_request)
admin.site.site_header = "InvenTree Admin" admin.site.site_header = "InvenTree Admin"
@ -164,6 +164,11 @@ frontendpatterns = [
re_path(r'^accounts/email/', CustomEmailView.as_view(), name='account_email'), re_path(r'^accounts/email/', CustomEmailView.as_view(), name='account_email'),
re_path(r'^accounts/social/connections/', CustomConnectionsView.as_view(), name='socialaccount_connections'), re_path(r'^accounts/social/connections/', CustomConnectionsView.as_view(), name='socialaccount_connections'),
re_path(r"^accounts/password/reset/key/(?P<uidb36>[0-9A-Za-z]+)-(?P<key>.+)/$", CustomPasswordResetFromKeyView.as_view(), name="account_reset_password_from_key"), re_path(r"^accounts/password/reset/key/(?P<uidb36>[0-9A-Za-z]+)-(?P<key>.+)/$", CustomPasswordResetFromKeyView.as_view(), name="account_reset_password_from_key"),
# Temporary fix for django-allauth-2fa # TODO remove
# See https://github.com/inventree/InvenTree/security/advisories/GHSA-8j76-mm54-52xq
re_path(r'^accounts/two_factor/remove/?$', CustomTwoFactorRemove.as_view(), name='two-factor-remove'),
re_path(r'^accounts/', include('allauth_2fa.urls')), # MFA support re_path(r'^accounts/', include('allauth_2fa.urls')), # MFA support
re_path(r'^accounts/', include('allauth.urls')), # included urlpatterns re_path(r'^accounts/', include('allauth.urls')), # included urlpatterns
] ]

View File

@ -28,6 +28,7 @@ from allauth.account.models import EmailAddress
from allauth.account.views import EmailView, PasswordResetFromKeyView from allauth.account.views import EmailView, PasswordResetFromKeyView
from allauth.socialaccount.forms import DisconnectForm from allauth.socialaccount.forms import DisconnectForm
from allauth.socialaccount.views import ConnectionsView from allauth.socialaccount.views import ConnectionsView
from allauth_2fa.views import TwoFactorRemove
from djmoney.contrib.exchange.models import ExchangeBackend, Rate from djmoney.contrib.exchange.models import ExchangeBackend, Rate
from user_sessions.views import SessionDeleteOtherView, SessionDeleteView from user_sessions.views import SessionDeleteOtherView, SessionDeleteView
@ -36,7 +37,7 @@ from common.settings import currency_code_default, currency_codes
from part.models import PartCategory from part.models import PartCategory
from users.models import RuleSet, check_user_role from users.models import RuleSet, check_user_role
from .forms import EditUserForm, SetPasswordForm from .forms import CustomTOTPDeviceRemoveForm, EditUserForm, SetPasswordForm
def auth_request(request): def auth_request(request):
@ -761,3 +762,12 @@ class NotificationsView(TemplateView):
"""View for showing notifications.""" """View for showing notifications."""
template_name = "InvenTree/notifications/notifications.html" template_name = "InvenTree/notifications/notifications.html"
# Temporary fix for django-allauth-2fa # TODO remove
# See https://github.com/inventree/InvenTree/security/advisories/GHSA-8j76-mm54-52xq
class CustomTwoFactorRemove(TwoFactorRemove):
"""Use custom form."""
form_class = CustomTOTPDeviceRemoveForm
success_url = reverse_lazy("settings")

View File

@ -8,7 +8,7 @@ coveralls==2.1.2 # Coveralls linking (for Travis)
cryptography==3.4.8 # Cryptography support cryptography==3.4.8 # Cryptography support
django-admin-shell==0.1.2 # Python shell for the admin interface django-admin-shell==0.1.2 # Python shell for the admin interface
django-allauth==0.48.0 # SSO for external providers via OpenID django-allauth==0.48.0 # SSO for external providers via OpenID
django-allauth-2fa==0.9 # MFA / 2FA django-allauth-2fa==0.9 # MFA / 2FA # IMPORTANT: Do only change after reviewing GHSA-8j76-mm54-52xq
django-cleanup==5.1.0 # Manage deletion of old / unused uploaded files django-cleanup==5.1.0 # Manage deletion of old / unused uploaded files
django-cors-headers==3.2.0 # CORS headers extension for DRF django-cors-headers==3.2.0 # CORS headers extension for DRF
django-crispy-forms==1.11.2 # Form helpers django-crispy-forms==1.11.2 # Form helpers