I have a django backend and I have enabled Cross origin requests as follows:
INSTALLED_APPS = [
..
'corsheaders',
]
MIDDLEWARE = [
'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',
'django.middleware.security.SecurityMiddleware',
'corsheaders.middleware.CorsMiddleware',
]
CORS_ORIGIN_ALLOW_ALL = True
I haven't implemented any authentication. I simply am trying to hit an API endpoint and trying to fetch data on my Angular2 frontend.
I have implemented a session based cart in Django backend which stores my products (https://github.com/lazybird/django-carton). When I hit http://127.0.0.1:8000/api/shopping-cart/show/ through my browsable api it gives me
{"1":{"product_pk":1,"price":"23000.00000","quantity":3},"2":{"product_pk":2,"price":"34000.00000","quantity":7},"4":{"product_pk":4,"price":"450.00000","quantity":1}}
However when I try to hit the same url from my Angular2 service: it throws me error:
XMLHttpRequest cannot load http://127.0.0.1:8000/api/shopping-cart/show/. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:3000' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
My service call is as follows:
private myUrl: string = 'http://127.0.0.1:8000/api/shopping-cart/'
showCart(){
return this.http.get(this.myUrl + 'show' + '/', {withCredentials:true})
.toPromise()
.then(response => response.json())
}
Note: If I remove {withCredentials:true} then it does not send sessionid or csrftoken and returns {} but the error vanishes. What am I doing wrong?
In my Django settings I had to add:
CORS_ALLOW_CREDENTIALS= True
AFAIK if you use withCredentials: true you can't use * for Access-Control-Allow-Origin but need http://localhost:3000 instead.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Origin
Access-Control-Allow-Origin: <origin> | *
The origin parameter specifies a URI that may access the resource. The browser must enforce this. For requests without credentials, the server may specify "*" as a wildcard, thereby allowing any origin to access the resource.
You middleware order problem. Try this
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
]
Note that CorsMiddleware needs to come before Django's CommonMiddleware
You can use angular2 integrated proxy.
create proxy.conf.json file
in proxy.conf write:
{
"/api/shopping-cart/": {
"target": "http://localhost:8000",
"secure": false
}
}
in your package.json change "start" script to:
"start": "ng serve --proxy-config proxy.conf.json"
run "npm start" in your command line
Related
So I have a backend with django and I am using react native for frontend. I added a emulator in android studio.
And when I start the backend like: python manage.py runserver I can run also the frontend with expo start.
But now I want to fetch the data with react native. So I start the backend with:
python manage.py runserver 192.168.1.68:19000 - settings file of django:
INSTALLED_APPS = [
'corsheaders',
'DierenWelzijnAdmin.apps.DierenwelzijnadminConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ALLOWED_HOSTS = ['192.168.1.68', '127.0.0.1', ]
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = [
"http://localhost:8081",
"http://localhost:19006",
"http://localhost:19002",
"http://192.168.1.69:8000",
"http://192.168.1.68:19000",
]
CORS_ALLOW_METHODS = [
"DELETE",
"GET",
"OPTIONS",
"PATCH",
"POST",
"PUT",
]
CORS_ALLOW_HEADERS = [
"accept",
"accept-encoding",
"authorization",
"content-type",
"dnt",
"origin",
"user-agent",
"x-csrftoken",
"x-requested-with",
]
And react native service:
export const fetchCategoryData = async () => {
try {
const response = await fetch("http://192.168.1.68:19000/animal/categories/main_groups/", {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
//setCategoryData(data);
} catch (error) {
console.error("There was a problem with the fetch operation:", error);
throw error;
}
};
And when I then start the react native app with expo start and I do a r after a.
I get this message:
warn No apps connected. Sending "reload" to all React Native apps failed. Make sure your app is running in the simulator or on a phone connected via USB.
The emulator I installed from android studio is: Pixel 2 XL and if I do: adb devices
I see the emulator:
List of devices attached
emulator-5554 device
And I already whiped the data several times from the emulator.
Question:
How to run the react native for fetching data from the backend?
Oke, I changed the backend to:
192.168.1.68:8000
and in frontend also:
192.168.1.68:8000
and it works now :)
This was indeed very stupid of me. Because I did fetch('//192.168.1.68:19000'). But that is my emulator host. Of course that doesn't work
I'm learning how to develop a website using Angular and Django. I got this error from my Angular localhost:
Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/user/' from origin
'http://localhost:4200' has been blocked by CORS policy: Response to preflight request
doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
In django's settings.py I have installed a custom users app, rest_framework and corsheaders app
Besides that, I have included this config:
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
I've stacked the middleware in this way:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware', #CORS middleware
'users.middleware.AuthenticationMiddleware', #custom middleware for jwt
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
I've got no CORS errors with login and register requests from my angular app but the problem appeared when I used a middleware to check if a jwt header had been supplied (and test if it was valid or if it had expired). I added that middleware to settings.py file and that request worked fine in Postman so I tried to implement it from Angular.
This is the method:
validateToken(): Observable<boolean> {
const url = `${this.baseUrl}/user/`;
const headers = new HttpHeaders().set(
'jwt',
localStorage.getItem('token') || ''
);
return this.http
.get<AuthResponse>(url, {
headers,
})
.pipe(
map((resp) => {
localStorage.setItem('token', resp.jwt);
this._user = resp.user;
return resp.ok;
}),
catchError((err) => of(false))
);
However, I'm getting the error I showed before. Have any of you gone through this same problem with Angular and Django before and know how it could be solved?
PS: I've tried to install 'Allow CORS: Access-Control-Allow-Origin' Chrome extension but when I used it I still got this error:
Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/user/' from origin 'http://localhost:4200'
has been blocked by CORS policy: Response to preflight request doesn't pass access control check:
It does not have HTTP ok status.
There you have a screenshot of preflight request and response from browser's network tab:
On your headers variable you need to set a pair of property:value containing the missing access control property:
'Access-Control-Allow-Origin' : '*'
In production my app is giving me CSRF verification failed when I log into my admin panel.
I have the following in my settings.py:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'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',
]
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
As my site doesn't currently have an SSL certificate I have ignored the following after running python manage.py check --deploy:
?: (security.W004) You have not set a value for the SECURE_HSTS_SECONDS setting. If your entire site is served only over SSL, you may want to consider setting a value and enabling HTTP Strict Transport Security. Be sure to read the documentation first; enabling HSTS carelessly can cause serious, irreversible problems.
?: (security.W008) Your SECURE_SSL_REDIRECT setting is not set to True. Unless your site should be available over both SSL and non-SSL connections, you may want to either set this setting True or configure a load balancer or reverse-proxy server to redirect all connections to HTTPS.
If you use those two settings then you must be using SSL.
See:
SESSION_COOKIE_SECURE
CSRF_COOKIE_SECURE
I want to block calls to my Django REST API (www.backend_django.com) from unknown origins, for example, I have a website under the domain "www.example.com" I want to allow only to this site to be able to do request to my API.
In order to do this, I have configured Django-Cors-Headers in the following way:
DEBUG = False
ALLOWED_HOSTS = ["www.backend_django.com", "backend_django.com"]
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
'https://backend_django.com',
'https://www.backend_django.com',
'https://example.com',
'https://www.example.com', )
CSRF_TRUSTED_ORIGINS = [
'backend_django.com',
'example.com']
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'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',
'social_django.middleware.SocialAuthExceptionMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
]
In order to test it, I have done a call from Postman using my computer and have successfully done a request still to the API.
Did I set up something bad in the settings? How can I archive this?
CORS restrictions won't prevent other hosts from making direct requests to your API.
If you need granular restrictions then you could use something like django-iprestrict.
If you need to restrict the whole backend app it's easier via web server settings .htaccess or similar.
The server answer with a Access-Control-Allow-Origin value set for the production. Is there a way to be permissive when the requests come from my development server ? Is there a Django setting to disable the cross-origin check when DEBUG=True for example ?
I can't modify the Access-Control-Allow-Origin. The request is made with jquery ajax function.
EDIT:
I've installed https://github.com/ottoyiu/django-cors-headers with pip install django-cors-headers, added the following in my settings.py
if DEBUG:
INSTALLED_APPS += ('corsheaders', )
CORS_ORIGIN_ALLOW_ALL = DEBUG
And put the middleware :
MIDDLEWARE_CLASSES = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
...
}
But I still get the error :
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at _request_url_. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
If I inspect the response header, I don't see any Access-Control-Allow-Origin parameter.
Install middleware: https://github.com/ottoyiu/django-cors-headers
In django settings.py add following setting:
DEBUG=True
CORS_ORIGIN_ALLOW_ALL = DEBUG
(if DEBUG is true Access-Control-Allow-Origin will be added to headers in response)
To add CORS headers to your response, install this to your django project:
https://github.com/ottoyiu/django-cors-headers
Since you want to connect from local, you cannot whitelist a particular host alone.
To enable CORS only when you have DEBUG=True, you can add corsheaders to your installed apps only when Debug is True:
if DEBUG is True:
INSTALLED_APPS += ('corsheaders', )