CORS policy blocks XMLHttpRequest - django

With Ionic Angular running in on my localhost I made this call to my Django backend (running on different localhost):
test() {
return this.httpClient.get(endpoint + '/test', {
headers: { mode: 'no-cors' },
});
}
And on the backend side I have following code to respond:
#csrf_exempt
def test(request):
response = json.dumps({'success': True})
return HttpResponse(response, content_type='application/json', headers={'Access-Control-Allow-Origin': '*'})
I have also this in my settings.py file:
INSTALLED_APPS = [
...
'corsheaders',
]
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
]
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True
Still, I get this error message in my console:
Access to XMLHttpRequest at 'http://127.0.0.1:8000/test' from origin 'http://localhost:8100' has been blocked by CORS policy: Request header field mode is not allowed by Access-Control-Allow-Headers in preflight response.
What am I doing wrong?

You need to just add one more setting
CORS_ALLOW_ALL_HEADERS=True
Other than the above you do not need to set a header on each response. Just simply respond back with payload as
#csrf_exempt
def test(request):
response = json.dumps({'success': True})
return HttpResponse(response, content_type='application/json', headers={'Access-Control-Allow-Origin': '*'})

Related

CORS headers not showing up in my request/response on Django

I've made the following CORS implementation on my Django project using django-cors-headers.
CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOWED_ORIGINS = []
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
....
]
INSTALLED_APPS = [
...
'corsheaders',
]
For some reason, I don't see the effect of these headers (I don't have Access-Control-Allow-Origin in my headers). I print out the request and response headers in my view. This is my view:
def payment(request, *args, **kwargs):
print(request.headers)
params_in = json.loads(request.body.decode('utf-8'))
headers_in = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer key,
}
response = requests.post('https://url.com/v1/endpoint',
headers=headers_in,
data=params_in)
resp_out = Response(response.json()['value'])
print(resp_out.headers)
return resp_out
My request headers are ['Host', 'Connection', 'Content-Type', 'Origin', 'Accept-Encoding', 'Cookie', 'Accept', 'User-Agent', 'Referer', 'Accept-Language', 'X-Request-Id', 'X-Forwarded-For', 'X-Forwarded-Proto', 'X-Forwarded-Port', 'Via', 'Connect-Time', 'X-Request-Start', 'Total-Route-Time', 'Content-Length'] and my only resp_out header is 'Content-Type'.
Why could this be? What am I missing?
You don't receive the CORS headers as a part of the request rather the Access-Control-Allow-Origin: Your_Origin_Name(if among the allowed ones mentioned in CORS_ALLOWED_ORIGINS = []
) header will be sent back as a response header.

How to solve django and angular cors errors

I'm developing application and got this error:
Access to XMLHttpRequest at 'https://subdomain.domain.org/api/parks/?page_size=6&page_number=1' from origin ''https://subdomain.domain.org' 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.
Django Config
setting.py:
INSTALLED_APPS = [
...
'corsheaders',
...
]
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
ALLOWED_HOSTS = ['app_name-backend.herokuapp.com']
CORS_ALLOWED_ORIGINS = [
'https://app_name-frontend.herokuapp.com',
'https://subdomain.domain.org',
]
CORS_ALLOW_ALL_ORIGINS = False
Angular Requests
service.ts:
getParks(filters: any=null, parameters:any=null): Observable<any> {
...
var httpHeaders = new HttpHeaders();
httpHeaders.set('Content-Type', 'application/json');
httpHeaders.set('Access-Control-Allow-Origin', '*');
var requestUrl = this.baseServiceUrl + this.serviceUrl;
return this.httpClient.get<any>(requestUrl, { params: httpParams, headers: this.httpHeaders })
.pipe(
...
),
catchError(this.handleError<Park[]>('Park getParks', []))
);
}
The front and back are hosted on heroku
Any idea how to fix it ?
Thanks in advance.

Django doesn't create session cookie in cross-site json request

I want to make cross-site JavaScript call from third-party domain (in this case my desktop/localhost server) to my remote Django server hosted on my_domain.com/ and calling REST WS exposed on my_domain.com/msg/my_service with using session/cookies for storing session state.
But when I call this service (hosted on remote Django server) from my desktop browser or localhost Django server (JS is in index.html), Django doesn't create session cookie and on remote server are doesn't store session state. But when i call this service from Postman or from same localhost JS to localhost instance of same Django service it works and session is created.
My JS script in index.html which make call to WS send_message:
fetch('http://my_domain.com/ws/my_service', {
method:"POST",
credentials: 'include',
body:JSON.stringify(data)
})
.then(res => res.json())
.then(json => {
showResponse(json.message);
})
When I run this script from my desktop browser or my localhost server it runs correctly with cookies and sessions parameters.
Django my_service implementation view
#csrf_exempt
def my_service(request):
if request.method == "POST":
message_bstream= request.body
request.session.set_expiry(0)
message= json.loads(message_bstream)
out,sta=state_machine_response(message["message"],int(request.session["state"]))
request.session["state"] =sta
respo={"message":out}
response = HttpResponse(json.dumps(respo), content_type="application/json")
response.set_cookie(key='name', value='my_value', samesite='None', secure=True)
#return JsonResponse(respo, safe=False, status=200)
return response
else:
return HttpResponseNotFound ("Sorry this methode is not allowed")
Or I try generate response like
return JsonResponse(respo, safe=False, status=200)
My settings.py
INSTALLED_APPS = [
...
'corsheaders',
]
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
'http://localhost:8000',
)
CORS_ALLOWED_ORIGINS = [
'http://localhost:8000',
]
CSRF_TRUSTED_ORIGINS = [
'http://localhost:8000',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SAMESITE = 'None'
Please do you have any idea?
You can't save cookies from a third-party API call unless you use SameSite=None with the Secure option in the Set-Cookie header. You can achieve this for the sessionid and CSRF cookie with the following settings:
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SAMESITE = 'None'
In this case, you must use the HTTPS protocol scheme.
Another solution would be to use a proxy, which is helpful in a localhost development environment. This is an example using vue.js on the vue.config.js file:
const { defineConfig } = require('#vue/cli-service')
if (process.env.NODE_ENV == "development"){
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
proxy: {
"^/api/": {
target: process.env.VUE_APP_BASE_URL,
changeOrigin: true,
logLevel: "debug",
pathRewrite: { "^/api": "/api" }
}
}
},
})
}
Some useful doc https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#samesitenone_requires_secure

Django CSRF and axios post 403 Forbidden

I use Django with graphene for back-end and Nuxt for front-end. The problem appears when I try post requests from nuxt to django. In postman everything works great, in nuxt I receive a 403 error.
Django
# url.py
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', GraphQLView.as_view(graphiql=settings.DEBUG,
schema=schema)),
]
# settings.py
CORS_ORIGIN_WHITELIST = 'http://localhost:3000'
CORS_ALLOW_CREDENTIALS = True
CSRF_USE_SESIONS = False
CSRF_COOKIE_HTTPONLY = False
CSRF_COOKIE_SAMESITE = None
NuxtJs
# nuxt.config.js
axios: {
baseURL: 'http://127.0.0.1:8000/',
debug: false,
progress: true,
credentials: true
},
# plugins/axios.js
await $axios.onRequest((config) => {
config.headers.common['Content-Type'] = 'application/json'
config.xsrfCookieName = 'csrftoken'
config.xsrfHeaderName = 'X-CSRFToken'
const csrfCookie = app.$cookies.get('csrftoken')
config.headers.common['X-CSRFToken'] = csrfCookie
console.log(config)
# store/contact.js
import { AddMessage } from '../queries/contact.js'
export const actions = {
async send() {
const message = await this.$axios({
url: 'api/',
method: 'POST',
data: AddMessage
})
}
}
# queries/contact.js
export const AddMessage = {
query: `
mutation AddContact($input: AddMessageInput!){
addMessage(input: $input){
message{
name
email
body
terms
}
}
}
`,
variables: `
{
"input":{
"name": "test",
"email": "test#test.com",
"body": "test",
"terms": true,
}
}
`,
operationName: 'AddMessage'
}
Somethig that
Here are request headers from axios post. Something strange for me is the cookie with a wrong value. The good value of token is present in X-CSRFToken header.
Here is the log from axios post request. Another strange thing for me is the undefined headers: Content-Type and X-CSRFToken
Thank you!
I resolved this problem and I want to share the solution here.
The problem with wrong cookie value was generated by the front end app that managed (I don't remember how) to get csrf cookie from the back end app. In X-CSRFToken header was token received from response's Set-cookie header and in Cookie header was the cookie from back end app.
After I changed localhost with 127.0.0.1 and added
config.xsrfCookieName = 'csrftoken' in axios plugin
I was able to separate the apps, save and use cookies independent.
The second problem, with undefined headers was generated by axios. These 2 line of code resolved the problem. These were added also in axios onRequest method.
config.xsrfHeaderName = 'X-CSRFToken'
config.headers['Content-Type'] = 'application/json'

Cors error.. Cross-Origin Request Blocked

I am trying XHR GET request on a python-flask based API and getting this error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://..... (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
The server code:
from flask_restful import Api
from flask_cors import CORS
application_root = config.get_application_root()
static_folder = os.path.join(application_root, 'static')
template_folder = os.path.join(application_root, 'templates')
app = Flask(__name__, static_url_path='/static', static_folder=static_folder, template_folder=template_folder)
cors = CORS(app)
app.config['SQLALCHEMY_DATABASE_URI'] ='mysql://*********'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['PROPAGATE_EXCEPTIONS'] = True # To allow flask propagating exception even if debug is set to false on app^M
api = Api(app)
#app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
return response
api.add_resource(TestResults, '/results')
if __name__ == '__main__':
db.init_app(app)
app.run(host='0.0.0.0', debug=True) # important to mention debug=True^M
The response header still doesn't get the required header.
Content-Length 2452
Content-Type application/json
Date Tue, 06 Nov 2018 06:52:06 GMT
Server Werkzeug/0.14.1 Python/3.4.7
What am I missing here...