Getting 403 for unsafe methods | DRF React Production - django

I'm getting 403 forbidden error for the unsafe methods (PUT, POST, DELETE) in the deployed Django project. I'm using react as front-end.
I'm using axios to send the request to the DRF view. I've included the below lines to send the csrf token with the header as X-CSRFToken.
axios.defaults.xsrfHeaderName = "X-CSRFToken";
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.withCredentials = true;
In my local everything is working fine. I've deployed this project with NGINX and Gunicorn in a Linux server. There I'm facing an issue while sending the request with unsafe methods. I'm not sure why its not working when it is deployed in the Linux server.
Can anyone please help me on this. Please :(

Related

Django CSRF Failed: CSRF token missing or incorrect when using client on localhost

I am using django 3.2 , i had implemented csrf using below link
Link
Everything works fine when using same domain for client and server.
But while testing locally i get the error when sending post, put or delete requests.
I can see csrftoken in the request headers under cookie, but can't see it using document.cookie.
csrftoken is non httponly cookies, still i don't know why it not visible in document.cookie in client side.
You have to add CSRF_TRUSTED_ORIGINS = ["localhost:3000"] inside your settings.py to allow post requests.
I finally got the solution,
Since my backend was running on other domain not on localhost.
I had added proxy for all the requests, so that they appear to be coming from same origin.
In Angular, it ca be done like below:
proxy.conf.json
{
"/**": {
"target": "<your backend url>",
"secure": false,
"changeOrigin": true
}
}
then run using,
ng serve --proxy-config proxy.conf.json

Django in Docker on Nginx request to self fails when in the context of another request

I have a Django application deployed inside a container on top of Nginx using Dokku. One of the view functions of the Django application includes a request:
views.py
def foo(request):
...
response = requests.get(url)
...
It is probably noteworthy that url is the url of the Django application itself, so the request is from the application to itself. The request is to one of the API endpoints (the reasons for doing this are historical). When the view is called then the request to url fails with 504 gateway timeout.
I cannot reproduce this in any other context specifically:
There is no error when running on localhost with the development server, where url is then the url of the development app (localhost to itself works).
There is no error when running on localhost with the development server, where I manually make the url the production url (localhost to production works).
There is no error when running this request on the production server but outside of the view. Specifically, I did a docker exec into the container, started the Django environment (manage.py shell), and ran the exact request that the view was making, and it worked! (production to production works)
It seems that only when the request is made in the context of a view which itself is answering another request I get an issue.
Any ideas?

How to solve ERR_TOO_MANY_REDIRECT when deploying django rest framework web app to Azure?

I deployed an web app which django restframework base on Heroku and Azure.
Same app on Heroku works fine.
But when I access to Azure, it causes ERR_TOO_MANY_REDIRECT error.
I googled and found that turn SECURE_SSL_REDIRECT off solved ERR_TOO_MANY_REDIRECT error.
However, it causes 403 CSRF error instead.
I need to find another way to fix ERR_TOO_MANY_REDIRECT or find a way to fix 403 CSRF error.
Can anyone help me to solve this issue?
If your app is on "Azure App Service", the HTTPS connection will be terminated before it reaches your web worker. Your app wil see an incoming HTTP request instead. In this case you need to set SECURE_SSL_REDIRECT = False indeed. If you want to enforce HTTPS (which is a good practice) you can do so in the Azure settings: https://learn.microsoft.com/en-us/azure/app-service/configure-ssl-bindings#enforce-https
About the CSRF-related error: because Azure translates HTTPS to HTTP, you need to configure Django to allow POST requests from a different scheme (since Django 4.0) by adding this to settings.py:
CSRF_TRUSTED_ORIGINS = ["https://YOUR-DOMAIN.com", "https://www.YOUR-DOMAIN.com"]
If this does not solve your problem, you can temporarily set DEBUG = True in production and try again. On the error page, you will see a "Reason given for failure" that you can post here.

React Django REST framework session is not persisting/working

I'm working on a project with Django Rest Framework as back-end and React as front-end. When I set a session variable initially in some function/view and later when I try to access the different view through axios call and in that view if I try to access session variable which i created previously, I get KeyError. Session doesn't seem stored.
I googled I got a similar issue which I'm facing.
Django rest framework Reactjs sessions not working
I followed the process by adding { withCredentials: true } in axios call. Now I'm getting a different error. Now the issue is not able to access the backend. I get an error saying Access to XMLHttpRequest at 'http://127.0.0.1:8000/url/' from origin 'http://localhost:3000' has been blocked by CORS policy
Again I googled the issue which I'm getting and found that I've to add CORS_ORIGIN_WHITELIST in the django settings.py
I followed the below post for that
Django Python rest framework, No 'Access-Control-Allow-Origin' header is present on the requested resource in chrome, works in firefox
I have added CORS_ORIGIN_WHITELIST like this
CORS_ORIGIN_WHITELIST = [
'http://localhost:3000',
'http://127.0.0.1:3000'
]
Still, I'm facing the same issue. I don't know what's going wrong.
Finally after so much of research I found a solution for this.
In the file where we are importing axios to make the call, set the default header below your import
axios.defaults.withCredentials = true;
example:
import axios from "axios";
axios.defaults.withCredentials = true;
axios.get("url")
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error);
});
once this is done go to your settings.py file and add the below configuration
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
so after this if you set a session variable and access it later in any view, you would be able to get the value which you had previously stored.
This solution worked for me. Hopefully if anyone has the same issue, it will work for them too. :)
NOTE
If the session is not storing under localhost:3000 then make sure that you're accessing your front-end application through 127.0.0.1:3000. If you access the front-end application through localhost and if your backend is running on 127.0.0.1 then the session cookie will be set to 127.0.0.1, so changing the front-end URL from localhost:3000 to 127.0.0.1:3000 will solve your problem.
I had a similar issue once. I used firefox as a browser and got the problem solved by installing the CORS everywhere plugin for firefox (https://addons.mozilla.org/en-US/firefox/addon/cors-everywhere/). So, if you're using firefox, this might solve your problem.

Django + Angular + Django-allauth

I'm creating a web application using Django as the backend and Angular for the front.
Angular is running on a Yeoman stack on localhost:9000 while Django is running on localhost:8000 and I'm using grunt-contrib-proxy to redirect all the $http calls from angular at /api to the django port. So for example, if Angular asks for localhost:9000/api/hello this will be redirect to localhost:8000/api/helloand django will serve it.
I'm planning to setup Django Rest Framework for serving all the Angular request to the /api path.
So far so good.
Now, I have an already configured and working installation of Django-allauth for making Oauth authentication to third party services. It does work using plain old Django but I have no idea how to make this work in conjunction with Angular.
The only thing that came into mind was serving the allauth views through django rest framework, but what about redirection after authentication? I can't wrap my mind around it.
Is it better to drop this approach and make the Oauth authentication straight from the front (Angular)?
EDIT:
I managed to call the login view from Angular
In grunt-contrib-proxy I've added the account context and rewrite rule:
context: ['/api', '/accounts'],
rewrite: {
'^/api': '/api',
'^/account': '/accounts'
}
I've made an ajax call from angular, asking for the allaluth login view (for example for github): $http.get('/accounts/github/login/?process=login')
The problem is that I get back:
XMLHttpRequest cannot load https://github.com/login/oauth/authorize?scope=&state=BlaBla&redirect…ub%2Flogin%2Fcallback%2F&response_type=code&client_id=BlaBlaBla. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. (index):1
(The BlaBla was added by me). I think I'm doing something totally wrong
You need to add an
Origin: http://localhost:9000
to the header in the request that angular sends to Django.
Also make sure the server running Django returns an
Access-Control-Allow-Origin: *
see here for more information.