From c3c35f076c579efce714f10f9a32af40897a7d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Behmo?= Date: Mon, 12 Jan 2015 18:14:12 +0100 Subject: [PATCH] Fix csrf error on studio login Context: We have witnessed multiple, seemingly random "CSRF verification failed" errors while signing in (with valid ID) to the Studio. Explanation: The login form does not initially include a CSRF field. The CSRF header of the request is appended to the studio login request headers by intercepting the form validation. This intercept is performed by the login.js script. Unfortunately, the login.js script is loaded pretty late (at the end of the template). So if the login form is validated sufficiently fast, the login.js script has no time to load and append the X-CSRFToken header to the request. Proposed solution: the CSRF token is already passed to the template via the login view, so we just add a hidden field to the login form to include the csrf token. --- .../contentstore/tests/test_contentstore.py | 33 +++++++++++++++++-- cms/static/js/factories/login.js | 1 - cms/templates/login.html | 1 + 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index f831edff01..89ca6208b3 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -4,7 +4,7 @@ import copy import mock from mock import patch import shutil -import lxml +import lxml.html from datetime import timedelta from fs.osfs import OSFS @@ -26,7 +26,7 @@ from contentstore.views.component import ADVANCED_COMPONENT_TYPES from xmodule.contentstore.django import contentstore from xmodule.contentstore.utils import restore_asset_from_trashcan, empty_asset_trashcan -from xmodule.exceptions import NotFoundError, InvalidVersionError +from xmodule.exceptions import InvalidVersionError from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore.inheritance import own_metadata @@ -1747,6 +1747,35 @@ class EntryPageTestCase(TestCase): self._test_page("/logout", 302) +class SigninPageTestCase(TestCase): + """ + Tests that the CSRF token is directly included in the signin form. This is + important to make sure that the script is functional independently of any + other script. + """ + + def test_csrf_token_is_present_in_form(self): + # Expected html: + #
+ # ... + #
+ # ... + # + # ... + #
+ # ... + #
+ response = self.client.get("/signin") + csrf_token = response.cookies.get("csrftoken") + form = lxml.html.fromstring(response.content).get_element_by_id("login_form") + csrf_input_field = form.find(".//input[@name='csrfmiddlewaretoken']") + + self.assertIsNotNone(csrf_token) + self.assertIsNotNone(csrf_token.value) + self.assertIsNotNone(csrf_input_field) + self.assertEqual(csrf_token.value, csrf_input_field.attrib["value"]) + + def _create_course(test, course_key, course_data): """ Creates a course via an AJAX request and verifies the URL returned in the response. diff --git a/cms/static/js/factories/login.js b/cms/static/js/factories/login.js index da35af0b28..fcf8ee3069 100644 --- a/cms/static/js/factories/login.js +++ b/cms/static/js/factories/login.js @@ -8,7 +8,6 @@ define(['jquery.cookie', 'utility'], function() { dataType: 'json', data: data, success: callback, - headers : {'X-CSRFToken':$.cookie('csrftoken')} }); } diff --git a/cms/templates/login.html b/cms/templates/login.html index c0ab813ae0..deb959861a 100644 --- a/cms/templates/login.html +++ b/cms/templates/login.html @@ -21,6 +21,7 @@ from django.utils.translation import ugettext as _
${_("Required Information to Sign In to {studio_name}").format(studio_name=settings.STUDIO_NAME)} +