mirror of
https://github.com/pretix/pretix.git
synced 2026-05-19 17:34:03 +00:00
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.
This commit is contained in:
@@ -27,11 +27,11 @@ from django.template import TemplateDoesNotExist, loader
|
|||||||
from django.template.loader import get_template
|
from django.template.loader import get_template
|
||||||
from django.utils.functional import Promise
|
from django.utils.functional import Promise
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.decorators.csrf import requires_csrf_token
|
|
||||||
from sentry_sdk import last_event_id
|
from sentry_sdk import last_event_id
|
||||||
|
|
||||||
from pretix.base.i18n import language
|
from pretix.base.i18n import language
|
||||||
from pretix.base.middleware import get_language_from_request
|
from pretix.base.middleware import get_language_from_request
|
||||||
|
from pretix.multidomain.middlewares import requires_csrf_token
|
||||||
|
|
||||||
|
|
||||||
def csrf_failure(request, reason=""):
|
def csrf_failure(request, reason=""):
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ from django.middleware.csrf import (
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.urls import set_urlconf
|
from django.urls import set_urlconf
|
||||||
from django.utils.cache import patch_vary_headers
|
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.deprecation import MiddlewareMixin
|
||||||
from django.utils.http import http_date
|
from django.utils.http import http_date
|
||||||
from django_scopes import scopes_disabled
|
from django_scopes import scopes_disabled
|
||||||
@@ -270,26 +271,50 @@ class CsrfViewMiddleware(BaseCsrfMiddleware):
|
|||||||
if request.session.get(CSRF_SESSION_KEY) != request.META["CSRF_COOKIE"]:
|
if request.session.get(CSRF_SESSION_KEY) != request.META["CSRF_COOKIE"]:
|
||||||
request.session[CSRF_SESSION_KEY] = request.META["CSRF_COOKIE"]
|
request.session[CSRF_SESSION_KEY] = request.META["CSRF_COOKIE"]
|
||||||
else:
|
else:
|
||||||
is_secure = request.scheme == 'https'
|
|
||||||
# Set the CSRF cookie even if it's already set, so we renew
|
# Set the CSRF cookie even if it's already set, so we renew
|
||||||
# the expiry timer.
|
# the expiry timer.
|
||||||
if is_secure and settings.CSRF_COOKIE_NAME in request.COOKIES: # remove legacy cookie
|
if request.is_secure() and settings.CSRF_COOKIE_NAME in request.COOKIES: # remove legacy cookie
|
||||||
# response.delete_cookie does not work as we might have set a partitioned cookie
|
# response.delete_cookie does not work as we might have set a partitioned cookie
|
||||||
delete_cookie_without_samesite(
|
delete_cookie_without_samesite(
|
||||||
request, response,
|
request, response,
|
||||||
settings.CSRF_COOKIE_NAME,
|
settings.CSRF_COOKIE_NAME,
|
||||||
path=settings.CSRF_COOKIE_PATH,
|
path=settings.CSRF_COOKIE_PATH,
|
||||||
secure=is_secure,
|
secure=request.is_secure(),
|
||||||
httponly=settings.CSRF_COOKIE_HTTPONLY
|
httponly=settings.CSRF_COOKIE_HTTPONLY
|
||||||
)
|
)
|
||||||
set_cookie_without_samesite(
|
set_cookie_without_samesite(
|
||||||
request, response,
|
request, response,
|
||||||
'__Host-' + settings.CSRF_COOKIE_NAME if is_secure else settings.CSRF_COOKIE_NAME,
|
'__Host-' + settings.CSRF_COOKIE_NAME if request.is_secure() else settings.CSRF_COOKIE_NAME,
|
||||||
request.META["CSRF_COOKIE"],
|
request.META["CSRF_COOKIE"],
|
||||||
max_age=settings.CSRF_COOKIE_AGE,
|
max_age=settings.CSRF_COOKIE_AGE,
|
||||||
path=settings.CSRF_COOKIE_PATH,
|
path=settings.CSRF_COOKIE_PATH,
|
||||||
secure=is_secure,
|
secure=request.is_secure(),
|
||||||
httponly=settings.CSRF_COOKIE_HTTPONLY
|
httponly=settings.CSRF_COOKIE_HTTPONLY
|
||||||
)
|
)
|
||||||
# Content varies with the CSRF cookie, so set the Vary header.
|
# Content varies with the CSRF cookie, so set the Vary header.
|
||||||
patch_vary_headers(response, ('Cookie',))
|
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
|
||||||
|
):
|
||||||
|
raise ValueError("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 equivalents instead.")
|
||||||
|
|
||||||
|
return super().process_response(request, response)
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ from django.utils.functional import cached_property
|
|||||||
from django.utils.http import url_has_allowed_host_and_scheme
|
from django.utils.http import url_has_allowed_host_and_scheme
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.decorators.cache import never_cache
|
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.decorators.debug import sensitive_post_parameters
|
||||||
from django.views.generic import FormView, ListView, View
|
from django.views.generic import FormView, ListView, View
|
||||||
|
|
||||||
@@ -55,6 +54,7 @@ from pretix.base.settings import PERSON_NAME_SCHEMES
|
|||||||
from pretix.base.signals import customer_created, customer_signed_in
|
from pretix.base.signals import customer_created, customer_signed_in
|
||||||
from pretix.helpers.compat import CompatDeleteView
|
from pretix.helpers.compat import CompatDeleteView
|
||||||
from pretix.helpers.http import redirect_to_url
|
from pretix.helpers.http import redirect_to_url
|
||||||
|
from pretix.multidomain.middlewares import csrf_protect
|
||||||
from pretix.multidomain.models import KnownDomain
|
from pretix.multidomain.models import KnownDomain
|
||||||
from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse
|
from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse
|
||||||
from pretix.presale.forms.customer import (
|
from pretix.presale.forms.customer import (
|
||||||
|
|||||||
Reference in New Issue
Block a user