Reputation: 4664
I'm using django 1.11.6
and python 3.5
on an ubuntu
server.
I have an api for user registration.
This is my curl
command:
curl -i -H 'Accept: application/json; indent=4' -X POST https://mydomain/users/:register/ -d "id=222111&firstname=andy&yearofbirth=2007&lastname=Chris&othernames="
When I use it in cygwin
I get this response which is the desired:
HTTP/1.1 200 OK
Date: Thu, 26 Oct 2017 06:41:00 GMT
Server: Apache/2.4.18 (Ubuntu)
Allow: POST, OPTIONS
Vary: Accept,Cookie
Content-Length: 188
X-CSRFToken: acY2oPGkkqkzBe9itBq56oFeTFAllqv2bS39c7TpPN9LlGh90E1FxsI0YXLlu1Vu
X-Frame-Options: SAMEORIGIN
Set-Cookie: csrftoken=QfxnUGTmrRi1MThcn8Qau5ytnt2NR8tdRVCuIY6rWe7dwlp3UbrKV9BfsLdN0JTF; expires=Thu, 25-Oct-2018 06:41:01 GMT; Max-Age=31449600; Path=/
Content-Type: application/json
{
"isnew": "true",
"user": {
"othernames": "",
"id": "222111",
"firstname": "Andy",
"yearofbirth": 2007,
"lastnames": "Chris"
}
}
As I can see, I have X-CSRFToken
header and `csrftoken' cookie.
When I try to run the same curl
command from postman
I get:
Forbidden (403)
CSRF verification failed. Request aborted.
You are seeing this message because this HTTPS site requires a 'Referer header' to be sent by your Web browser, but none was sent. This header is required for security reasons, to ensure that your browser is not being hijacked by third parties.
If you have configured your browser to disable 'Referer' headers, please re-enable them, at least for this site, or for HTTPS connections, or for 'same-origin' requests.
My function in views.py
is:
class ApiUserRegister(APIView):
permission_classes = ()
serializer_class = RegisterUserSerializer
def post(self, request):
serializer = RegisterUserSerializer(data=request.data)
# Check format and unique constraint
serializer.is_valid(raise_exception=True)
data = serializer.data
if User.objects.filter(id=data['id']).exists():
user = User.objects.get(id=data['id'])
is_new = "false"
resp_status = status.HTTP_200_OK
else:
user = User.objects.create(id=data['id'],
firstname=data['firstname'],
yearofbirth=data['yearofbirth'],
lastname=data['lastname'],
othernames=data['othernames'])
user.save()
is_new = "true"
resp_status = status.HTTP_201_CREATED
resp = {"user": serializer.get_serialized(user),
"isnew": is_new} #csrfmiddlewaretoken: csrf_token
return Response( resp, status=resp_status, headers = {"X-CSRFToken":get_token(request)})
Upvotes: 0
Views: 3625
Reputation: 373
We have the same issue, we figured that the URL we have some issue.
We have extra slash in the URL we are hitting. Even though in spring boot its getting to correct controller having some extra character character also but Query params are not working
Upvotes: 0
Reputation: 211
Django sets csrftoken cookie on login. After logging in, we can see the csrf token from cookies in the Postman. (see image) CSRFtoken from cookies
First approach...
We can grab this token and set it in headers manually. But this token has to be manually changed when it expires. This process becomes tedious to do it on an expiration basis.
Better way...
Instead, we can use Postman scripting feature to extract the token from the cookie and set it to an environment variable. In Test section of the postman, add these lines.
var xsrfCookie = postman.getResponseCookie("csrftoken"); postman.setEnvironmentVariable('csrftoken', xsrfCookie.value);
This extracts csrf token and sets it to an environment variable called csrftoken in the current environment. Now in our requests, we can use this variable to set the header.(see image) Set {{csrftoken}} in your header
When the token expires, we just need to log in again and csrf token gets updated automatically.
Thanks to @chillaranand from hackernoon.com for original post
Upvotes: 0
Reputation: 3664
You can create an additional view to generate CSRF tokens which you can first gather by a GET request.
Example:
# views.py
from django.middleware.csrf import get_token
class CSRFGeneratorView(APIView):
def get(self, request):
csrf_token = get_token(request)
return Response(csrf_token)
# urls.py
urlpatterns += [url(r'generate_csrf/$', views.CSRFGeneratorView.as_view())]
You can then call this view first to gain the CSRF token to use in further requests.
EDIT: After getting the token, you will add this to form data.
Example:
curl -X POST -d "csrfmiddlewaretoken=<token_value>" <url>
Ref: How CSRF works
Upvotes: 3