Opened 13 years ago

Closed 13 years ago

Last modified 12 years ago

#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)

03_add_csrf_ensure_cookie_decorator.diff (844 bytes ) - added by Chris Lamb 13 years ago.

Download all attachments as: .zip

Change History (13)

comment:1 by Gabriel Hurley, 13 years ago

Component: UncategorizedContrib apps
Triage Stage: UnreviewedAccepted

comment:2 by Valentin Golev, 13 years ago

Maybe there is a need for a setting, like

CSRF_COOKIE_IN_EVERY_RESPONSE = True

comment:3 by Valentin Golev, 13 years ago

Cc: me@… added

comment:4 by Gabriel Hurley, 13 years ago

Component: Contrib appscontrib.csrf

comment:5 by Łukasz Rekucki, 13 years ago

Severity: Normal
Type: Bug

comment:6 by Chris Lamb, 13 years ago

Cc: Chris Lamb 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.

comment:7 by Aymeric Augustin, 13 years ago

Easy pickings: unset

#15925 was a duplicate.

comment:8 by Luke Plant, 13 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.

comment:9 by Luke Plant, 13 years ago

Resolution: fixed
Status: newclosed

In [16192]:

Fixed #15354 - provide method to ensure CSRF token is always available for AJAX requests

Thanks to sayane for the report.

comment:10 by anonymous, 13 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.

in reply to:  10 comment:11 by Luke Plant, 13 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.

comment:12 by Jacob, 12 years ago

milestone: 1.3

Milestone 1.3 deleted

Note: See TracTickets for help on using tickets.
Back to Top