codingrhythm
codingrhythm

Reputation: 1546

django does not send csrf token again after browser cookies has been cleared

In normal situation, django will send csrf token via cookie which can be used by ajax post method later. However when I clear cookies in the browser(Chrome or Firefox), the csrf token is not sent to browser anymore, the session id is still sending but no csrf token. Does anyone know what's going wrong?

I solved this issue by adding {% csrf_token %} to my template and the SET-COOKIE header appears along with that page request. it turns out that you have to put the {%csrf-token%} in the template in order to make the server send the token via SET-COOKIE header

Upvotes: 12

Views: 8485

Answers (4)

Denis
Denis

Reputation: 11

In my case, the problem was VSCode debugger. I turned on server via VSCode debug mode, then open new incognito window (obviously there were no cookies), and django stopped setting missing cookie. When I started server as normal, the problem has gone.

Upvotes: 1

Han He
Han He

Reputation: 3461

I had the same problem. After debugging against django source, the reason is:

If your view is not rendering a template containing the csrf_token template tag, Django might not set the CSRF token cookie.

Two solutions:

  • Add {% csrf_token %} in your template
  • Use @ensure_csrf_cookie decorator for your view

For detail your can refer django doc.

Upvotes: 5

Alfishe
Alfishe

Reputation: 3680

In most cases issue caused by second check mentioned in a previous answer

if not request.META.get("CSRF_COOKIE_USED", False):
        return response

This can be solved by using @ensure_csrf_cookie decorator for the view. If used - check is passed and cookie is set/renewed each time view is rendered.

See also related topic: Using ajax request in Django without form element

Upvotes: 0

Pavel Reznikov
Pavel Reznikov

Reputation: 3208

Look at django/middleware/csrf.py in which CsrfViewMiddleware class is declared. As you can see in def process_response(self, request, response) there are three conditions that prevent cookie setup:

def process_response(self, request, response):
    if getattr(response, 'csrf_processing_done', False):
        return response

    # If CSRF_COOKIE is unset, then CsrfViewMiddleware.process_view was
    # never called, probaby because a request middleware returned a response
    # (for example, contrib.auth redirecting to a login page).
    if request.META.get("CSRF_COOKIE") is None:
        return response

    if not request.META.get("CSRF_COOKIE_USED", False):
        return response

    # Set the CSRF cookie even if it's already set, so we renew
    # the expiry timer.
    response.set_cookie(settings.CSRF_COOKIE_NAME,
                        request.META["CSRF_COOKIE"],
                        max_age = 60 * 60 * 24 * 7 * 52,
                        domain=settings.CSRF_COOKIE_DOMAIN,
                        path=settings.CSRF_COOKIE_PATH,
                        secure=settings.CSRF_COOKIE_SECURE
                        )
    # Content varies with the CSRF cookie, so set the Vary header.
    patch_vary_headers(response, ('Cookie',))
    response.csrf_processing_done = True
    return response

Check which is applied for you.

Upvotes: 7

Related Questions