thebjorn
thebjorn

Reputation: 27351

Is this csrf failure expected?

Given the following series of events

  1. anonymous user opens home page, which contains a form (with a valid csrf token)
  2. the user opens a secondary tab and logs in.
  3. the user returns to the original tab and submits the form.

Is the resulting csrf failure expected, and if so, are there any solutions that will give the user a better experience?

Upvotes: 0

Views: 748

Answers (2)

thebjorn
thebjorn

Reputation: 27351

For this exact issue, and provided Django's CSRF_COOKIE_HTTPONLY has its default value of False, this onfocus handler seems to work:

$(document).ready(function () {
    $(window).on('focus', function () {

         var cookie_csrf = dk.web.cookie.get('csrftoken');  // or Cookie.get(..) or something similar
         var dom_csrf = $('[name=csrfmiddlewaretoken]:first');

         if (cookie_csrf !== dom_csrf) {
             // other tab has caused the csrf cookie to change
             $('[name=csrfmiddlewaretoken]').each(function () {
                 $(this).val(cookie_csrf);
             });
         }
    });
});

it seems a bit hackish, so perhaps refreshing the page is "better":

if (cookie_csrf !== dom_csrf) {
    window.location.reload(true);  // reload the current page, without using the cache
}

refreshing the page will get any changes to the page that results from logging in, but delete any input the user has entered.

It's safe to access the csrf token from .js assuming you have no XSS vulnerabilities (which is generally assumed when it comes to csrf).

This technique relies on the fact that the value of the csrf token in the cookie and in the dom are identical, which they are in Django by design.

Upvotes: 0

metatoaster
metatoaster

Reputation: 18938

Yes, this is part of the security system. Given that the CSRF token belonged to the anonymous user could potentially be generated/acquired by the attacker (as they are anonymous users also), it is definitely not a wise idea to use that token after the user has logged in. Django documents this behavior as a security measure, and they have a relevant ticket documenting why they do this.

This is also why some sites (such as github) will warn the user that they need to reload the page on all other tabs of the users' browser session if a login/logout was done in one tab. There is no safe measure to avoid this.

Upvotes: 2

Related Questions