forked from CGM_Public/pretix_original
Fix customer views using wrong csrf middleware (#6027)
* Fix customer views using wrong csrf middleware This lead to persistent csrf validation errors if the token from the cookie expired, which could only be solved by clearing cookies. * Remove unneccesary csrf_protect decorators * Fix typo Co-authored-by: Raphael Michel <michel@pretix.eu> --------- Co-authored-by: Raphael Michel <michel@pretix.eu>
This commit is contained in:
committed by
pajowu
co-authored by
Raphael Michel
parent
e19908571c
commit
76e6803eac
@@ -27,11 +27,11 @@ from django.template import TemplateDoesNotExist, loader
|
||||
from django.template.loader import get_template
|
||||
from django.utils.functional import Promise
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.decorators.csrf import requires_csrf_token
|
||||
from sentry_sdk import last_event_id
|
||||
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.middleware import get_language_from_request
|
||||
from pretix.multidomain.middlewares import requires_csrf_token
|
||||
|
||||
|
||||
def csrf_failure(request, reason=""):
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import itertools
|
||||
import re
|
||||
from http.cookies import Morsel
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ from django.middleware.csrf import (
|
||||
from django.shortcuts import render
|
||||
from django.urls import set_urlconf
|
||||
from django.utils.cache import patch_vary_headers
|
||||
from django.utils.decorators import decorator_from_middleware
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
from django.utils.http import http_date
|
||||
from django_scopes import scopes_disabled
|
||||
@@ -216,7 +217,8 @@ class SessionMiddleware(BaseSessionMiddleware):
|
||||
request.session.save()
|
||||
if is_secure and settings.SESSION_COOKIE_NAME in request.COOKIES: # remove legacy cookie
|
||||
# response.delete_cookie does not work as we might have set a partitioned cookie
|
||||
thoroughly_delete_cookie(response,
|
||||
thoroughly_delete_cookie(
|
||||
response,
|
||||
settings.SESSION_COOKIE_NAME,
|
||||
path=settings.SESSION_COOKIE_PATH,
|
||||
secure=is_secure,
|
||||
@@ -278,12 +280,13 @@ class CsrfViewMiddleware(BaseCsrfMiddleware):
|
||||
|
||||
# remove legacy cookie
|
||||
if request.is_secure() and settings.CSRF_COOKIE_NAME in request.COOKIES:
|
||||
thoroughly_delete_cookie(response,
|
||||
settings.CSRF_COOKIE_NAME,
|
||||
path=settings.CSRF_COOKIE_PATH,
|
||||
secure=request.is_secure(),
|
||||
httponly=settings.CSRF_COOKIE_HTTPONLY
|
||||
)
|
||||
thoroughly_delete_cookie(
|
||||
response,
|
||||
settings.CSRF_COOKIE_NAME,
|
||||
path=settings.CSRF_COOKIE_PATH,
|
||||
secure=request.is_secure(),
|
||||
httponly=settings.CSRF_COOKIE_HTTPONLY
|
||||
)
|
||||
|
||||
handle_duplicated_csrftoken(request, response)
|
||||
|
||||
@@ -299,6 +302,19 @@ class CsrfViewMiddleware(BaseCsrfMiddleware):
|
||||
# Content varies with the CSRF cookie, so set the Vary header.
|
||||
patch_vary_headers(response, ('Cookie',))
|
||||
|
||||
def process_response(self, request, response):
|
||||
if (
|
||||
not settings.CSRF_USE_SESSIONS
|
||||
and request.is_secure()
|
||||
and settings.CSRF_COOKIE_NAME in response.cookies
|
||||
and response.cookies[settings.CSRF_COOKIE_NAME].value
|
||||
):
|
||||
logger.warning("Usage of djangos CsrfViewMiddleware detected (legacy cookie found in response). "
|
||||
"This may be caused by using csrf_project or requires_csrf_token from django.views.decorators.csrf. "
|
||||
"Use the pretix.multidomain.middlewares equivalent instead.")
|
||||
|
||||
return super().process_response(request, response)
|
||||
|
||||
|
||||
def handle_duplicated_csrftoken(request, response):
|
||||
# Due to a Safari bug, in some browser, two csrftoken cookies can exist:
|
||||
@@ -317,4 +333,16 @@ def handle_duplicated_csrftoken(request, response):
|
||||
secure=request.is_secure(),
|
||||
path=settings.CSRF_COOKIE_PATH,
|
||||
httponly=settings.CSRF_COOKIE_HTTPONLY
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
csrf_protect = decorator_from_middleware(CsrfViewMiddleware)
|
||||
|
||||
|
||||
class _EnsureCsrfToken(CsrfViewMiddleware):
|
||||
# Behave like CsrfViewMiddleware but don't reject requests or log warnings.
|
||||
def _reject(self, request, reason):
|
||||
return None
|
||||
|
||||
|
||||
requires_csrf_token = decorator_from_middleware(_EnsureCsrfToken)
|
||||
|
||||
@@ -44,7 +44,6 @@ from django.utils.http import url_has_allowed_host_and_scheme
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.decorators.cache import never_cache
|
||||
from django.views.decorators.csrf import csrf_protect
|
||||
from django.views.decorators.debug import sensitive_post_parameters
|
||||
from django.views.generic import FormView, ListView, View
|
||||
|
||||
@@ -101,7 +100,6 @@ class LoginView(RedirectBackMixin, FormView):
|
||||
redirect_authenticated_user = True
|
||||
|
||||
@method_decorator(sensitive_post_parameters())
|
||||
@method_decorator(csrf_protect)
|
||||
@method_decorator(never_cache)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.organizer.settings.customer_accounts:
|
||||
@@ -213,7 +211,6 @@ class RegistrationView(RedirectBackMixin, FormView):
|
||||
redirect_authenticated_user = True
|
||||
|
||||
@method_decorator(sensitive_post_parameters())
|
||||
@method_decorator(csrf_protect)
|
||||
@method_decorator(never_cache)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.organizer.settings.customer_accounts:
|
||||
@@ -257,7 +254,6 @@ class SetPasswordView(FormView):
|
||||
template_name = 'pretixpresale/organizers/customer_setpassword.html'
|
||||
|
||||
@method_decorator(sensitive_post_parameters())
|
||||
@method_decorator(csrf_protect)
|
||||
@method_decorator(never_cache)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.organizer.settings.customer_accounts:
|
||||
@@ -301,7 +297,6 @@ class ResetPasswordView(FormView):
|
||||
template_name = 'pretixpresale/organizers/customer_resetpw.html'
|
||||
|
||||
@method_decorator(sensitive_post_parameters())
|
||||
@method_decorator(csrf_protect)
|
||||
@method_decorator(never_cache)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.organizer.settings.customer_accounts:
|
||||
@@ -527,7 +522,6 @@ class ChangePasswordView(CustomerAccountBaseMixin, FormView):
|
||||
form_class = ChangePasswordForm
|
||||
|
||||
@method_decorator(sensitive_post_parameters())
|
||||
@method_decorator(csrf_protect)
|
||||
@method_decorator(never_cache)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.organizer.settings.customer_accounts:
|
||||
@@ -561,7 +555,6 @@ class ChangeInformationView(CustomerAccountBaseMixin, FormView):
|
||||
form_class = ChangeInfoForm
|
||||
|
||||
@method_decorator(sensitive_post_parameters())
|
||||
@method_decorator(csrf_protect)
|
||||
@method_decorator(never_cache)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.organizer.settings.customer_accounts:
|
||||
@@ -669,7 +662,6 @@ class SSOLoginView(RedirectBackMixin, View):
|
||||
redirect_authenticated_user = True
|
||||
|
||||
@method_decorator(sensitive_post_parameters())
|
||||
@method_decorator(csrf_protect)
|
||||
@method_decorator(never_cache)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.organizer.settings.customer_accounts:
|
||||
@@ -732,7 +724,6 @@ class SSOLoginReturnView(RedirectBackMixin, View):
|
||||
redirect_authenticated_user = True
|
||||
|
||||
@method_decorator(sensitive_post_parameters())
|
||||
@method_decorator(csrf_protect)
|
||||
@method_decorator(never_cache)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.organizer.settings.customer_accounts:
|
||||
|
||||
Reference in New Issue
Block a user