@@ -310,6 +310,45 @@ def get_context_data(self, **kwargs):
310310 context ["mobile" ] = self .request .GET .get ("ui" )
311311 return context
312312
313+ def render_to_response (self , context , ** response_kwargs ):
314+ """
315+ Override to delete CSRF cookie when session cookie is not present.
316+ This cleans up CSRF cookies for anonymous users.
317+ TODO: december 2025 - remove this override, cookies should have been cleared
318+ """
319+ response = super ().render_to_response (context , ** response_kwargs )
320+
321+ session_cookie_name = settings .SESSION_COOKIE_NAME
322+ has_session = session_cookie_name in self .request .COOKIES
323+ has_csrf_cookie = "csrftoken" in self .request .COOKIES
324+
325+ # only delete CSRF cookie if user was previously logged in but session expired
326+ if (
327+ has_csrf_cookie
328+ and not has_session
329+ and self .request .session .session_key is None
330+ ):
331+ # check if user is on pages that require CSRF but don't require login
332+ # (auth pages where anonymous users submit forms)
333+ referer = self .request .META .get ("HTTP_REFERER" , "" )
334+ current_path = self .request .path
335+
336+ # paths that anonymous users can access and have forms
337+ anonymous_form_paths = [
338+ "/accounts/" , # login, signup, password reset, email confirm, etc.
339+ "/socialaccount/" , # social auth pages
340+ ]
341+
342+ # don't delete if user is on or coming from anonymous form pages
343+ is_anonymous_form = any (
344+ path in referer for path in anonymous_form_paths
345+ ) or any (path in current_path for path in anonymous_form_paths )
346+
347+ if not is_anonymous_form :
348+ response .delete_cookie ("csrftoken" , path = "/" )
349+
350+ return response
351+
313352
314353class DeleteUserView (LoginRequiredMixin , FormView ):
315354 template_name = "users/delete.html"
0 commit comments