From 029756e576c9c062d78636edae50d65102cd2838 Mon Sep 17 00:00:00 2001 From: daveoconnor Date: Thu, 16 Oct 2025 11:05:17 -0700 Subject: [PATCH] Account for CDN with csrf cookie generation (#1958) (#1963) --- libraries/forms.py | 2 +- templates/includes/_header.html | 3 --- templates/users/profile.html | 15 +++++++++++++ users/views.py | 39 +++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/libraries/forms.py b/libraries/forms.py index d8c5110e..7986af0b 100644 --- a/libraries/forms.py +++ b/libraries/forms.py @@ -916,7 +916,7 @@ class CommitAuthorEmailForm(Form): ensure the email exists.""" email = self.cleaned_data.get("email") commit_author_email = CommitAuthorEmail.objects.filter( - email_iexact=email + email__iexact=email ).first() msg = None diff --git a/templates/includes/_header.html b/templates/includes/_header.html index 9d121850..b0926c18 100644 --- a/templates/includes/_header.html +++ b/templates/includes/_header.html @@ -94,7 +94,4 @@ guide.classList.remove("hidden"); } } - document.body.addEventListener('htmx:configRequest', function(event) { - event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}'; - }); diff --git a/templates/users/profile.html b/templates/users/profile.html index 13b1dd7d..5118e174 100644 --- a/templates/users/profile.html +++ b/templates/users/profile.html @@ -152,4 +152,19 @@ {% include "modal.html" %} + + {% endblock %} diff --git a/users/views.py b/users/views.py index c2035cb0..777befe7 100644 --- a/users/views.py +++ b/users/views.py @@ -310,6 +310,45 @@ class UserAvatar(TemplateView): context["mobile"] = self.request.GET.get("ui") return context + def render_to_response(self, context, **response_kwargs): + """ + Override to delete CSRF cookie when session cookie is not present. + This cleans up CSRF cookies for anonymous users. + TODO: december 2025 - remove this override, cookies should have been cleared + """ + response = super().render_to_response(context, **response_kwargs) + + session_cookie_name = settings.SESSION_COOKIE_NAME + has_session = session_cookie_name in self.request.COOKIES + has_csrf_cookie = "csrftoken" in self.request.COOKIES + + # only delete CSRF cookie if user was previously logged in but session expired + if ( + has_csrf_cookie + and not has_session + and self.request.session.session_key is None + ): + # check if user is on pages that require CSRF but don't require login + # (auth pages where anonymous users submit forms) + referer = self.request.META.get("HTTP_REFERER", "") + current_path = self.request.path + + # paths that anonymous users can access and have forms + anonymous_form_paths = [ + "/accounts/", # login, signup, password reset, email confirm, etc. + "/socialaccount/", # social auth pages + ] + + # don't delete if user is on or coming from anonymous form pages + is_anonymous_form = any( + path in referer for path in anonymous_form_paths + ) or any(path in current_path for path in anonymous_form_paths) + + if not is_anonymous_form: + response.delete_cookie("csrftoken", path="/") + + return response + class DeleteUserView(LoginRequiredMixin, FormView): template_name = "users/delete.html"