0

I'm a tester at a company that's using a django backend. I want to write a test that modifies a user by posting form data to one of the django admin screens. Our backend testing environment is protected via basic auth at the firewall, and then uses a csrf token when communicating with django. I am able to use basic auth to get to the django server, and then I can actually log into the site using csrf, and get the server to send me the test user's accou nt page. But when posting right back to that same endpoint with my data changes, it fails for csrf validation (CSRF token missing or incorrect). I can't figure out why csrf validation works in some instances, but not in others. Can anyone tell me what I'm doing wrong? I've created a mvp out of my code that attempt to elucidate the issue. Hopefully, someone out there knows what I'm doing wrong.

    session = requests.Session()
    auth = requests.auth.HTTPBasicAuth('redacted', 'redacted')
    session.auth = auth
    url = "http://local.redacted.dev/ouadm/login/"

    response = session.get(url, params={'next': '/ouadm/'}, allow_redirects=True)

    session.headers['Referer'] = 'https://redacted.com/ouadm/login/'
    csrfmiddlewaretoken = response.cookies['csrftoken']
    data = {'csrfmiddlewaretoken': csrfmiddlewaretoken, 'username': 'testuser', 'password': 'password'}
    response = session.post(url, data=data, params={'next': '/ouadm/'}, allow_redirects=True)

    data = {'csrfmiddlewaretoken': csrfmiddlewaretoken, 'csrftoken': csrfmiddlewaretoken, 'username': 'testuser',
            'first_name': 'joe', 'last_name': 'user',
            'email': 'testuser@redacted.com', 'is_active': 'on', 'is_staff': 'on', 'is_superuser': 'on',
            'groups': '6',
            'groups': '13', 'groups': '18', 'groups': '21', 'groups': '16', 'groups': '11',
            'user_permissions': '334',
            'user_permissions': '16', 'last_login_0': '2016-05-25', 'last_login_1': '14,32,04',
            'date_joined_0': '2015-10-26',
            'date_joined_1': '15,44,35', 'initial-date_joined_0': '2015-10-26', 'initial-date_joined_1': '15,44,35',
            '_save': 'Save'}
    #desperate much?
    session.headers['HTTP_X_CSRFToken'] = csrfmiddlewaretoken
    session.headers['HTTP_X_OU_AUTH_TOKEN'] = csrfmiddlewaretoken
    session.headers['X-CSRFToken'] = csrfmiddlewaretoken

    response = session.get('http://local.redacted.dev/ouadm/auth/user/11/', data=data, allow_redirects=True)
    session.headers.update({'Referer':'http://local.redacted.dev/ouadm/auth/user/11/'})
    response = session.post('http://local.redacted.dev/ouadm/auth/user/11/', data=data, allow_redirects=True)
Goishin
  • 45
  • 1
  • 6
  • which version of django are you on ? – quemeraisc Jun 07 '16 at 16:48
  • possible duplicate http://stackoverflow.com/questions/13567507/passing-csrftoken-with-python-requests – Alexander Davydov Jun 07 '16 at 16:52
  • might you forgot headers parameter in your post request? – Alexander Davydov Jun 07 '16 at 16:53
  • @quemeraisc: django 1.8 – Goishin Jun 07 '16 at 16:57
  • @AlexanderDavydov: The problem is that the csrf token is used in the first session.post line. So, it seems like it works. It's the second use of session.post where it doesn't appear to work. Is there some other field I need to update or something? – Goishin Jun 07 '16 at 16:58
  • Could you explain what is the use of sending exactly same kind of request but one get and another post in your last and third last lines of code? – Vikas Ojha Jun 07 '16 at 22:08
  • @Vikas Neha Ojha: Sure, Vikas. I noticed with the first request (the get) I get a csrf token, and then in the second request (the post) I use it. This pattern worked to log in. And desperation made me try it for the second set of requests. – Goishin Jun 08 '16 at 15:49
  • No, thats not the way it should be done. Try to inspect he flow of get and post request using Chrome's developer console or any other tool. Then replicate those as it is. – Vikas Ojha Jun 09 '16 at 06:50

0 Answers0