Search code examples
pythonapiauthenticationpython-requestscsrf

Can't connect to specific API from python code using 'requests' library


I am trying to get my python code to connect to a specific API following below guide:

https://github.com/specify/specify7/wiki/API-Documentation-Demo

I can make it work from a Linux CLI as specified, but trying to emulate this process via python only yields 403 errors. Inspecting the request, I can see that the headers are set correctly and the data is actually parsed into the request body, so getting close, but so far no cigar.

#Connect to Specify7 API
# First step is to get a CSRF token 
csrftoken = requests.get(loginUrl).cookies.get('csrftoken')
print('CSRF Token: ', csrftoken)

# Next step is to use csrf token to log in 
headers = {'X-CSRFToken': csrftoken, 'Referer' : baseUrl }
data = {"username" : "testy", "password" : "redacted", "collection": 4}
response = requests.put(loginUrl, json=data, headers=headers)

print('REQUEST: ', response.request.headers)
print('RESPONSE: ', response.status_code)
print(response.headers)
print()
print('***closer look at prepared request***')
print(response.request.method)
print(response.request.headers['Content-Type'])
print(response.request.headers['Referer'])
print(response.request.headers['X-CSRFToken'])
print(response.request.body)

Can anyone tell me what I'm missing here???


Solution

  • The curl client from the guide uses -b and -c options so that it handles cookies like a browser would do: The csrftoken cookie that is received with the GET request must be sent again with the subsequent PUT request. The header token is thus "bound" to the session cookie, for extra protection.

    Your python code does behave like a browser in this regard. Your PUT request must additionally send a cookie named csrftoken whose value is the csrftoken variable.