Best security practices for React + Django - django

I'm currently working on a project that uses Django API server and a NodeJS server running React. In development we're running Django on port 8000 and NodeJS on port 8080, and currently React is responsible for rendering the page and interacting with Django API, which provides data for React. In order for React to call Django APIs, we've enabled CORS in Django since they're on different ports.
My question is the following:
Is it safe to allow all CORS in production?
If not using the templates system by Django, is the site still protected against CSRF by defaults? If not, how to prevent CSRF in such settings (React+Django)?

Yes, it's safe to use CORS in production if you allow it for the correct origin domains. For example, if you are using django-cors-headers, use CORS_ORIGIN_ALLOW_ALL=False and a set of domains for CORS_ORIGIN_WHITELIST.
As the answers to this question explain, DRF uses CSRF tokens if using SessionAuthentication. However, if you are using other authentication mechanism (for example, token authentication or JWT) you are however also protected by the client browser not allowing unsecure requests from untrusted origins, i.e. not in your CORS_ORIGIN_WHITELIST. See answers to this question regarding security of CORS vs. CSRF token to prevent CSRF in general.

Related

How to set up javascript and django applications to exchange jwt tokens

I have a SAP implemented on the Netlify platform. The processing for the app is implemented in a django api running on a hosted server.
Users are authenticated on the Netlify app, but do not need to be authenticated in django.
I now want authorised users to be able to post data to the api and the django server objects with the message
Forbidden (CSRF cookie not set.): /api/save-archive/{...}/
I am looking at implementing JWT cookies and have considered djangorestframework_simplejwt but that seems to require that the user is authenticated in django
My question is, what software elements do I need to be able to generate and consume a token is this scenario?

Accept only authentificated requests to backend

I have this question. I am quite new in this area.
I have web app.
This consist of services deployed on Docker engine.
The main services/containers are:
Frontend : React on Nginx web server
Backend (API) : Django, DRF on gunicorn on Nginx
For frontend I use Auth0 provider. It works as expected. If user is not authenticated/authorized it is redirected to login page.
Now I want also to "secure" my backend that it only would accept authenticated connections from frontend.
For backend (Django) I also have CORS enabled (django-cors-headers package), but I still can connect from my browser my-site/api/ and get the response.
Does anybody know which strategy should I use.
Should I somehow secure it using JWT tokens. Somehow pass it to backend in my request?
There is various ways of authorizing API calls from your front-end applications to execute actions on your back-end. These will tend to vary in a few aspects:
Complexity
Needing to know who sent the request
Access surfaces
Duration of access
Roles
and so on...
In this case if you have authenticated users on your front-end using AuthO then a JWT could make sense since using this method you can encode specific user data that will allow you to make the decision on your backend as to if that user should have access to that action at that time.
Here is an article explaining a few popular methods of authentication

How to use csrf if using django just as REST API without frontend

I am currently using Django only as an API that contains no templates or HTML (frontend is on other server), it is just used to be requested. How do I enable csrf protection for POST requests if I don't have access to the csrf?

Django REST API set allowed hosts for individual endpoints

I would like to have different values for ALLOWED_HOSTS for different Django REST API endpoints. Is this possible? Here are more details:
I have a setup consisting of a Django REST API backend, a React frontend, a Postgresdb and nginx, each running in a docker container, managed by docker compose. I am exposing Django API endpoints that are accessed by the frontend from the user's browser, so I am adding the domain of the frontend to allowed hosts. However, I have one specific API endpoint that should only accept requests from the frontend docker container but never accept requests from outside. It should only be used for communication between the frontend and the backend container. So in this case i would have to restrict allowed hosts to the ip of the docker container. Both settings are possible and working, but I can only choose one of both in the global Django settings. My question is: Is it possible to set allowed hosts for an individual endpoint/url?
I suppose if there is no clean way of doing it I could run a manual check using HttpRequest.get_host() to verify the request host against the container name?
It's certainly possible.
In a pure Django context, I'd implement this as a Django middleware that intercepts the request, looks at the path and the request host, source IP and does what it needs to.
In a Django REST Framework context, I'd implement this as an additional authentication class, since it will then have access to the Django REST Framework context if required.
Finally, I'd recommend also protecting this "secret" endpoint with additional authentication – the simplest might be an additional secret header (X-Nik-Secret: very? ;-) ) that is known to the frontend container. That check can similarly be implemented in middleware or authentication.

Is it possible to fix the port number for graphql altair?

I'm using Django as backend providing a GraphQL API. I'm using Django's builtin support for Cross Site Request Forgery protection (CSRF protection) and django-cors-headers to enable the use of the Cross-origin resource sharing (CORS) mechanism. To debug the API I'm using Altair. Can I define a fixed port number for altair that I can consider altair as trusted origin in the Django settings.py file (CSRF_TRUSTED_ORIGINS).
I'm a maintainer of the Altair GraphQL Client. Depending on how you choose to use Altair (with the browser extensions, or with the desktop apps), it might be possible to get past the CORS protection. By default, the browser extensions don't follow the CORS protection and can make requests with the same origin policy. If you're using the desktop apps, you can set the Origin header to get the requests to appear as coming from the same origin.
As for the CSRF token-based protection, one of the techniques you can use to solve it would be using pre request scripts as described in this article: https://sirmuel.design/pre-requests-now-available-in-altair-graphql-client-c3b28892059c.