Why does Selenium cause CSRF 403?

I am trying to create a simple login test using Django and Selenium, but I get 403 due to CSRF failure. I expect the middleware to add a cookie to the GET request and then parse it into POST.

Here is what I have checked so far:

1. Is the cookie in the GET request set to /accounts/login/ ?

Yes, the cookie is set in the process_response method

2. Is a cookie available for the Selenium driver?

Yes

 ipdb> self.selenium.get_cookies() [{u'domain': u'localhost', u'name': u'csrftoken', u'value': u'DzNbEn9kZw0WZQ4OsRLouriFN5MOIQos', u'expiry': 1470691410, u'path': u'/', u'httpOnly': False, u'secure': True}] 

3. Is a cookie found during a POST request?

No, this try / except from django.middleware.CsrfViewMiddleware.process_view does not work:

source

 try: csrf_token = _sanitize_token( request.COOKIES[settings.CSRF_COOKIE_NAME]) # Use same token next time request.META['CSRF_COOKIE'] = csrf_token except KeyError: csrf_token = None # Generate token and store it in the request, so it's # available to the view. request.META["CSRF_COOKIE"] = _get_new_csrf_key() 

the code

 class TestLogin(StaticLiveServerTestCase): @classmethod def setUpClass(cls): cls.selenium = getattr(webdriver, settings.SELENIUM_WEBDRIVER)() cls.selenium.maximize_window() cls.selenium.implicitly_wait(5) super(TestLogin, cls).setUpClass() @classmethod def tearDownClass(cls): cls.selenium.quit() super(TestLogin, cls).tearDownClass() def test_login(self): self.selenium.get('{}{}'.format(self.live_server_url, '/accounts/login/?next=/')) assert "Django" in self.selenium.title un_el = self.selenium.find_element_by_id('id_username').send_keys('the_un') pw_el = self.selenium.find_element_by_id('id_password') pw_el.send_keys('the_pw') pw_el.send_keys(Keys.RETURN) try: WebDriverWait(self.selenium, 5).until(EC.title_contains("New Title")) except TimeoutException as e: msg = "Could not find 'New Title' in title. Current title: {}".format(self.selenium.title) raise TimeoutException(msg) finally: self.selenium.quit() 

Question

What can I try to debug this?

+4
source share
1 answer

An old question, but after it got stuck for several hours, the answer was simple.

From docs:

If the browser first connects via HTTP, which is the default for most browsers, it is possible that existing cookies will leak. For For this reason, you should set SESSION_COOKIE_SECURE and CSRF_COOKIE_SECURE to True. This tells the browser to send them only over HTTPS connections. Please note that this will mean that sessions will not work over HTTP, and CSRF protection will prevent any POST data from being received over HTTP (which would be great if you redirect all HTTP traffic to HTTPS).

Like me, you probably use django_extensions + Werkzeug for most of your work and, by default, runs all your local work through SSL.

If you are using a version of unittest or Djangos, I would recommend that you change these parameters during testing, for example:

 ... from django.conf import settings class ProfilePagetest(LiveServerTestCase): def setUp(self): settings.CSRF_COOKIE_SECURE = False settings.SESSION_COOKIE_SECURE = False self.url = reverse('clientpage:profile') self.username = ' name@names.com ' self.password = 'strange decisions...' get_user_model().objects.create_user(self.username, self.username, self.password) self.browser = webdriver.Firefox() 

This should stop CSRF validation problems.

+1
source

All Articles