diff --git a/src/pretix/control/templates/pretixcontrol/user/2fa_add.html b/src/pretix/control/templates/pretixcontrol/user/2fa_add.html index f7360f3994..8eab73d34f 100644 --- a/src/pretix/control/templates/pretixcontrol/user/2fa_add.html +++ b/src/pretix/control/templates/pretixcontrol/user/2fa_add.html @@ -6,6 +6,7 @@

{% trans "Add a two-factor authentication device" %}

{% csrf_token %} + {% bootstrap_form_errors form %} {% bootstrap_field form.name layout='horizontal' %} diff --git a/src/pretix/control/templates/pretixcontrol/user/2fa_confirm_totp.html b/src/pretix/control/templates/pretixcontrol/user/2fa_confirm_totp.html index 95b2f2715d..bcb85c8158 100644 --- a/src/pretix/control/templates/pretixcontrol/user/2fa_confirm_totp.html +++ b/src/pretix/control/templates/pretixcontrol/user/2fa_confirm_totp.html @@ -69,6 +69,7 @@ {% trans "Enter the displayed code here:" %} {% csrf_token %} + diff --git a/src/pretix/control/templates/pretixcontrol/user/2fa_delete.html b/src/pretix/control/templates/pretixcontrol/user/2fa_delete.html index 882b29f8ff..94ad855b99 100644 --- a/src/pretix/control/templates/pretixcontrol/user/2fa_delete.html +++ b/src/pretix/control/templates/pretixcontrol/user/2fa_delete.html @@ -6,6 +6,7 @@

{% trans "Delete a two-factor authentication device" %}

{% csrf_token %} +

{% blocktrans trimmed with device=device.name %} Are you sure you want to delete the authentication device "{{ device }}"? {% endblocktrans %}

diff --git a/src/pretix/control/templates/pretixcontrol/user/2fa_disable.html b/src/pretix/control/templates/pretixcontrol/user/2fa_disable.html index e4a5e39311..7e3d689914 100644 --- a/src/pretix/control/templates/pretixcontrol/user/2fa_disable.html +++ b/src/pretix/control/templates/pretixcontrol/user/2fa_disable.html @@ -6,6 +6,7 @@

{% trans "Disable two-factor authentication" %}

{% csrf_token %} +

{% trans "Do you really want to disable two-factor authentication?" %}

diff --git a/src/pretix/control/templates/pretixcontrol/user/2fa_enable.html b/src/pretix/control/templates/pretixcontrol/user/2fa_enable.html index c7a388d854..fbef80e275 100644 --- a/src/pretix/control/templates/pretixcontrol/user/2fa_enable.html +++ b/src/pretix/control/templates/pretixcontrol/user/2fa_enable.html @@ -7,6 +7,7 @@

{% trans "Enable two-factor authentication" %}

{% csrf_token %} +

{% trans "Do you really want to enable two-factor authentication?" %}

diff --git a/src/pretix/control/templates/pretixcontrol/user/2fa_leaveteams.html b/src/pretix/control/templates/pretixcontrol/user/2fa_leaveteams.html index 16048c075f..4ff5ccc4cd 100644 --- a/src/pretix/control/templates/pretixcontrol/user/2fa_leaveteams.html +++ b/src/pretix/control/templates/pretixcontrol/user/2fa_leaveteams.html @@ -6,6 +6,7 @@

{% trans "Leave teams that require two-factor authentication" %}

{% csrf_token %} +

{% trans "Do you really want to leave the following teams?" %}

diff --git a/src/pretix/control/templates/pretixcontrol/user/2fa_regenemergency.html b/src/pretix/control/templates/pretixcontrol/user/2fa_regenemergency.html index 88b8a491cd..b747f510bb 100644 --- a/src/pretix/control/templates/pretixcontrol/user/2fa_regenemergency.html +++ b/src/pretix/control/templates/pretixcontrol/user/2fa_regenemergency.html @@ -6,6 +6,7 @@

{% trans "Regenerate emergency codes" %}

{% csrf_token %} +

{% trans "Do you really want to regenerate your emergency codes?" %}

diff --git a/src/pretix/control/templates/pretixcontrol/user/change_email.html b/src/pretix/control/templates/pretixcontrol/user/change_email.html index 1d6e567005..1248cca495 100644 --- a/src/pretix/control/templates/pretixcontrol/user/change_email.html +++ b/src/pretix/control/templates/pretixcontrol/user/change_email.html @@ -8,6 +8,7 @@ {% trans "Change login email address" %} {% csrf_token %} + {% bootstrap_form_errors form %}

{% trans "This changes the email address used to login to your account, as well as where we send email notifications." %} diff --git a/src/pretix/control/templates/pretixcontrol/user/change_password.html b/src/pretix/control/templates/pretixcontrol/user/change_password.html index cdfe5bc5e4..e9ae9aa6e2 100644 --- a/src/pretix/control/templates/pretixcontrol/user/change_password.html +++ b/src/pretix/control/templates/pretixcontrol/user/change_password.html @@ -9,6 +9,7 @@
{% csrf_token %} + {% bootstrap_form_errors form %} {% bootstrap_field form.email %} {% bootstrap_field form.old_pw %} diff --git a/src/pretix/control/views/user.py b/src/pretix/control/views/user.py index dc03110307..f0023d4b2c 100644 --- a/src/pretix/control/views/user.py +++ b/src/pretix/control/views/user.py @@ -89,13 +89,31 @@ logger = logging.getLogger(__name__) class RecentAuthenticationRequiredMixin: max_time = 900 + max_form_time = 900 @method_decorator(never_cache) def dispatch(self, request, *args, **kwargs): - tdelta = time.time() - request.session.get('pretix_auth_login_time', 0) - if tdelta > self.max_time: + auth_is_recent = time.time() - request.session.get('pretix_auth_login_time', 0) < self.max_time + allowed_by_token = ( + request.session.pop('pretix_reauthed_flow_token', None) == request.POST.get('flow_token', '') + and request.session.pop('pretix_reauthed_flow_allowed_url', None) == request.get_full_path() + and time.time() - request.session.pop('pretix_reauthed_flow_start_time', 0) < self.max_form_time + ) + if auth_is_recent or allowed_by_token: + return super().dispatch(request, *args, **kwargs) + else: return redirect(reverse('control:user.reauth') + '?next=' + quote(request.get_full_path())) - return super().dispatch(request, *args, **kwargs) + + def get_flow_token(self): + self.request.session['pretix_reauthed_flow_allowed_url'] = self.request.get_full_path() + self.request.session['pretix_reauthed_flow_token'] = get_random_string(22) + self.request.session['pretix_reauthed_flow_start_time'] = time.time() + return self.request.session['pretix_reauthed_flow_token'] + + def get_context_data(self, **kwargs): + ctx = super().get_context_data() + ctx['flow_token'] = self.get_flow_token() + return ctx class ReauthView(TemplateView): @@ -283,6 +301,7 @@ class UserHistoryView(ListView): class User2FAMainView(RecentAuthenticationRequiredMixin, TemplateView): + max_time = 7200 template_name = 'pretixcontrol/user/2fa_main.html' def get_context_data(self, **kwargs): @@ -484,6 +503,7 @@ class User2FADeviceConfirmWebAuthnView(RecentAuthenticationRequiredMixin, Templa class User2FADeviceConfirmTOTPView(RecentAuthenticationRequiredMixin, TemplateView): template_name = 'pretixcontrol/user/2fa_confirm_totp.html' + max_form_time = 7200 # this should have effectively no timeout, as the user might need to download the 2fa app first @cached_property def device(self): @@ -556,6 +576,7 @@ class User2FALeaveTeamsView(RecentAuthenticationRequiredMixin, TemplateView): class User2FAEnableView(RecentAuthenticationRequiredMixin, TemplateView): template_name = 'pretixcontrol/user/2fa_enable.html' + max_form_time = 7200 # this should have effectively no timeout, as the user might take some time to print out their emergency codes, and they would become invalid in case of a timeout def dispatch(self, request, *args, **kwargs): if not any(dt.objects.filter(user=self.request.user, confirmed=True) for dt in REAL_DEVICE_TYPES):