Hi, I have deployed a web app and created a sub domain for it as the url of its backend (e.g main url is domain.com and subdomain is api.domain.com) and both are in https, too.
While I request from frontend to my created api in Django Rest Framework error Access to XMLHttpRequest has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource is given. Code below is the part of my settings.py.
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
ALLOWED_HOSTS = ['*']
INSTALLED_APPS = [
...
'corsheaders',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
I shall be thankful for giving me the possible solutions.
@adamchainz @KenWhitesell
Please do not tag specific individuals regarding questions or issues. We are all volunteers here, and answer questions as time, energy, and knowledge provide. About the only suggestion I can make would be for you to double-check your settings based upon the docs at django-cors-headers · PyPI.
I have completely checked my setting for multiple times based on that web page; But the error problem still persists and I need the solution ASAP.
Re-check the names of the settings variables you are using.
I have modified and edited my sent code for a lot of times but the error still persist. In localhost everything is fine but after deploying while requesting to backend by axios three errors are generated sequentially in the console in inspect element:
-Unchecked runtime.lastError: The message port closed before a response was received.
-Access to XMLHttpRequest at ‘…’ from origin ‘…’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
-GET ‘…’ net::ERR_FAILED 301 (Moved Permanently)
Hi again, the problem has been solved and that was with the ./htaccess of my backend subdomain.
Now, I have a question and will thank you for you answer.
I have a main domain which is for my Vue.js that is domain.com and I also have a sub-domain for my DRF backend with the name of api.domain.com; I do not want that the api and urls in my backend to be accessible under the corresponded url; e.g if anyone enters the url of api.domain.com/companies my backend info and data are being shown there but I want to remove access for anyone to see all of the pages of the backend subdomain. How can I do that?
Physically, you can’t.
If Vue.js is capable of issuing an http request to a url, then the browser - or any user-supplied JavaScript - would also be able to issue that same request.
About the best you can do is restrict access to logged-on users and limit the endpoints and data that can be requested based on that.
Dear Mr. Whitesell,
First, thank you for your reply.
Let me to state better what I mean.
Imagine my subdomain name for DRF is api.example.com; By putting code below in my settings.py, the DRF browsable interface for different APIs has been disabled and only what is being shown for different API pages (e.g api.example.com/drivers) is the data as you can see in the attached image in the bottom of the code.
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
],
}
Consider the API url of
api.example.com/drivers; In frontend (Vue.js and Axios) I have called this url to access whole of the data and queryset which the corresponded viewset is returning that (for all kind of users). But I do not want to any of my data to be shown while any user enter the link of
api.example.com/drivers; Previously, I’ve modified the ./htaccess file to redirect a user when enters any pages of the DRF APIs (as for all of my DRF API pages, I do not want that my data being shown on them according to the privacy) by code below:
RewriteCond %{HTTP_HOST} ^api\.example\.com$
RewriteRule ^(.*)$ "https://example.com/" [R=301,L]
The code above was OK and it redirects any users which enter the url of any of the DRF APIs but it made a problem and that was, all of my requests in code (with Vue,js and Axios) to access the data have been redirected, too as I do not want this.
If you need further explanation, please notify me otherwise I shall be thankful to you for your solution.
I understand what you’re saying.
I’m trying to explain to you that it simply isn’t possible.
Your server has no way to authoritatively determine that a request is coming from your Vue.js code and not the browser or some other JavaScript program.
Yeah, so how can I make my DRF APIs pages secure and disable them?
What is the normal and best solution (except of authentication)?
There isn’t one.
If it’s a publicly (non-authenticated) accessible api, you have no control over how it’s being accessed.
So, do all website which are developed with DRF have this problem? And their data is completely accessible with the url of the APIs?
This is not a DRF-specific issue. This is the case regardless of the framework, language, or system being used.
It is a fundamental property of the HTTP protocol.
Thank you for your responses.
So, can you give a solution which I can manage the access to my data to make them secure?
Yes. Authenticate the users and restrict access to authenticated users.
Considering @mghiasvandm issue, Can we possibly achieve this using middleware? The middleware would only allow requests from a particular type of app, specifically Vue.js in this case, while restricting requests from other sources. However, there are still security concerns. For instance, there are many Vue.js apps out there, so they could potentially make requests as well. My intention in joining in this topic is to learn more.