I am getting this error please haldle the csrf token in django project.When I first made an AJAX call with a POST request, I got a HTTP 403 Forbidden error. A quick debug led me to the CSRF authorisation problem. The backend refused to authorise the request because there is no accompanying CSRF token to prove that the request is not from a foreign site.
From the documentation:
"The CSRF middleware and template tag provides easy-to-use
protection against Cross Site Request Forgeries. This type of attack occurs when a malicious website contains a link, a form button
or some JavaScript that is intended to perform some action on your
website, using the credentials of a logged-in user who visits the
malicious site in their browser."
Therefore, when making a POST request, you should always include a CSRF token.
For more information, including how to use it with AJAX calls, please refer to the documentation:
https://docs.djangoproject.com/en/3.0/ref/csrf/
Related
I have a React frontend running at frontend.example.com and a Django backend with DRF running at backend.example.com. I am using Django Session Authentication and I want to properly implement CSRF protection.
Taking the React login page frontend.example.com/login as an example. It's the first time for a user to visit the page. There is a form with a user and password and on submit a new POST request is created to the Django backend. To the best of my knowledge, the CSRF token cookie should already be included in this request, right?
How to obtain that CSRF token from the Django backend? I am thinking of doing a GET request to the Django backend on loading the login-page to obtain that CSRF token cookie. Is that the way to do it or is there any other best practice?
Django has a section for AJAX request and how to handle CSRF: AJAX
Using this method you should send the token over and over again for each post request. The other method is using CORS. in this method, you only respond to the domains that you already whitelisted with headers that are whitelisted as well. So, instead of getting and passing CSRF token, you check if the request is coming from the right domain and then you can respond to it. And combining with a token system for user authentication, you should be good.
You can use this package for handling CORS if you use DRF: django-cors-headers
Using rate limiting can also help you avoid spams and robots to do noticeable harm.
Is it disabling CSRF functionality the best practice for Slack slash command server?
I want to call an API view function in Django by a Slack slash command, for example, /test.
When I call the URL for the view function with any browser (so it is a GET request), it works as expected.
However, when I run /test in Slack, I got 403_client_error in slack, and Forbidden (CSRF cookie not set) in the Django shell.
I believe this is because Slack sends a POST request, and Django requires CSRF token for any POST requests.
My question is whether I should disable CSRF checking for this view. Will there be a significant risk? Or is there any workaround?
Short Answer:
Yes, it's fine for an API endpoint.
Longer Answer:
Cross-Site Request Forgery (CSRF) Tokens are a means of preventing CSRF Attacks. These attacks basically work by placing some malicious code on another site that runs when the user visits that site. Upon loading the malicious site, some JavaScript code runs and submits a POST request to a site that the victim is already authenticated at. Since the user is already authenticated, the server for the other site—a bank, for example—thinks that the user is actually making this request—send the attacker $100, for example—and goes ahead and processes the request. Here is a really good description of CSRF Attacks and Tokens: https://stackoverflow.com/a/33829607/8068625
The way that CSRF Tokens prevent this is by putting a token somewhere on any page that contains a form and that token gets submitted as an additional field on the form when submitted. This way the page must actually be visited (which the attacker should not be able to accomplish) in order to submit the page.
So, as long as this page you are removing the CSRF protection from does not have a form on it that you would not like submitted by an attacker, it is fine to add #csrf_exempt to the view. It seems that this is the case since the endpoint exists solely as an API endpoint for a Slack Slash Command.
You might consider adding some other form of authentication for your API endpoints (note that CSRF is not for use in APIs) like, for example, JSON Web Tokens. But that is up to you.
We make react SPA with django-rest-framework on backend and use django-rest-auth for user authentication.
When user has logged in, we show him form for change profile data. When user submit this form, we take csrf token from cookie in login response, and put them in request X-CSRFToken header. Server responses that token is missing or incorrect.
If user refreshed the page, and repeated the same actions, csrf token is correct and profile data is updated.
How to solve this problem and why it occurs?
It looks like this is happening:
The login is successful
The cookie+token is created by the CSRF API and returned to the endpoint
The ready state executes some code not executed after the API response
The certificate is validated and the cookie+token is set in the database/app config/server-side cache during a GET request and/or by the ready state callback
Since there is no GET request until the refresh, the cookie+token is not centrally stored until then. Add a request to mimic what happens during the GET, then store it where it is currently being accessed for subsequent requests.
References
Issues with CSRF token and how to solve them | SAP Blogs
Why refresh CSRF token per form request? - Information Security Stack Exchange
CSRF Protection — Flask-WTF 0.14
CSRFGuard 3 Configuration - OWASP
Spring Security: Cross Site Request Forgery (CSRF)
Cross Site Request Forgery protection | Django documentation | Django
XSRF/CSRF Prevention in ASP.NET MVC and Web Pages | Microsoft Docs
Cross-Site Request Forgery is dead!
Still think you don't need HTTPS?
I'm using the chrome rest client to test the api calls.
A GET request is working fine but while making a POST request , getting 403 hidden response.
description is
CSRF verification failed. Request aborted
I'm setting as Content-Type=application/json.
One way would be to use #csrf_extempt, but seems to be good choice.
How to resolve above issue ?
Using #csrf_extempt is infact a good practice when you are providing an API to your site. Cross-site request forgery is what csrf is but in your case it won't be a forgery since an api can(should) be called from any site but yours.
.
Moreover sharing csrf token will prove to be very tricky.
In thre request, include an X-CSRFToken header with the CSRF token value obtained from the csrftoken cookie.
I don't get one thing about CSRF protection in django. For example we have some malicious site. What is the problem to send get-request from this site to csrf protected url, parse the page and get csrf value, then post with this value?
For example we have some malicious site. What is the problem to send
get-request from this site to csrf protected url, parse the page and
get csrf value, then post with this value?
If you do this, the session counterpart of the CSRF cookie will not match, and your request will be rejected.
Also, it should be noted that referrer check is done only for HTTPS requests to prevent a MitM vulnerability.
See this django wiki entry for a discussion on how CSRF protection works, and this SO question that discusses the MitM attack specifically.
The main purpose of Django's CSRF is explained in the Django Docs (https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#how-it-works):
This ensures that only forms that have originated from your Web site
can be used to POST data back.
So it checks several things - cookie, referrer, posted value. And there are some limitations, that you cannot always modify all these values at your will. For example - you can set X-CSRFToken token and the POST value in an AJAX call, but the browser will not allow you to override the referrer header... You might succeed to do a successful POST using urllib2 or similar library, but this is not covered by the CSRF protection, as it is the same as you POST on a page.
Again - CSRF means Cross Site Request Forgery and it is what it protects.
REFERRER will be checked. If the REFERRER does correspond to correct URL then POSTing data is not valid.