#15354 closed Bug (fixed)
Cookie with CSRF token not always available for AJAX Post requests
Reported by: | Sayane | Owned by: | nobody |
---|---|---|---|
Component: | CSRF | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | me@…, Chris Lamb | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Quote from mailing list:
There's a problem with CSRF Protection and XHR requests. It works perfectly if 'csrftoken' cookie has been set already. But what if it's not? Cookie with token will be set only, if META["CSRF_COOKIE_USED"] is True [1]. It's set to True in function get_token() [2]. get_token() is called in CsrfResponseMiddleware [3] (It's deprecated, i'm not using it) and in 'csrf' context processor (note - calling it is lazy, so I need to use {% csrf_token %} or at least get the value of csrf_token variable). But in my project i'm not using {% csrf_token %} anywhere. According to documentation [5] I'm not required to do anything else, but write a simple javascript code. Actually it's not true. I have to put "request.META['CSRF_COOKIE_USED'] = True" line in every view (or write appropriate decorator). What is more, it will affect users who didn't come across page where csrf_token is used, but their browser needs to send xhr post request. It affects svn version. I don't know if other versions are affected. [1] http://code.djangoproject.com/browser/django/trunk/django/middleware/csrf.py#L236 [2] http://code.djangoproject.com/browser/django/trunk/django/middleware/csrf.py#L67 [3] http://code.djangoproject.com/browser/django/trunk/django/middleware/csrf.py#L270 [4] http://code.djangoproject.com/browser/django/trunk/django/core/context_processors.py#L38 [5] http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
Attachments (1)
Change History (13)
comment:1 by , 14 years ago
Component: | Uncategorized → Contrib apps |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 14 years ago
comment:3 by , 14 years ago
Cc: | added |
---|
comment:4 by , 14 years ago
Component: | Contrib apps → contrib.csrf |
---|
comment:5 by , 14 years ago
Severity: | → Normal |
---|---|
Type: | → Bug |
comment:6 by , 14 years ago
Cc: | added |
---|---|
Has patch: | set |
I can't think of a nice *general* fix that doesn't involve a setting - we really do not want to speculatively set a CSRF cookie on every response (ie. remove the CSRF_COOKIE_USED flag checking) as that adds "Vary: Cookie" everywhere, uses entropy, bloats headers, etc. However, a patch for a setting enabling this for certain projects would be pretty trivial (just check for it in CsrfMiddleware.process_response).
My solution would be add a view decorator that ensures the CSRF cookie is set in the corresponding response. I'm attaching this now - it works well and is better than having to place a {% csrf_token %} inside a HTML comment or some other horrible hack.
by , 14 years ago
Attachment: | 03_add_csrf_ensure_cookie_decorator.diff added |
---|
comment:8 by , 14 years ago
I'm not going to use the patch here because it will only work if the middleware is enabled, and a function named ensure_csrf_cookie
is going to be less surprising if it doesn't have dependencies like that. I will close with a different implementation of ensure_csrf_cookie
soon.
follow-up: 11 comment:10 by , 14 years ago
Couldn't you just use:
from django.middleware.csrf import get_token
def some_view(request):
get_token(request)
seems simpler than a decorator.
comment:11 by , 14 years ago
Replying to anonymous:
Couldn't you just use...
This will only work if the CSRF middleware is installed, ensure_csrf_cookie
works in either case.
Maybe there is a need for a setting, like
CSRF_COOKIE_IN_EVERY_RESPONSE = True