I have an app where the frontend is using React and the backend is using django-rest-framework. The backend enforces CSRF which is needed, and I think everything will work fine in production because the backend and the frontend will share the same origin (https://mydomain.awesome).
But for local development I have a problem, my frontend is running on localhost:3000 and my backend is running on localhost:8000, and this means they are on different origins and my backend is not sending CSRF token to my frontend.
What do people do in this case? How can I have "same origin" in the local development environment?
You need to use a package called django-cors-headers
pip install django-cors-headers.
Then, in your Django project's settings.py, include the following line at the top of the MIDDLEWARE section:
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
'django.middleware.security.SecurityMiddleware',
... (other middlware)
]
Now, add the following lines in your settings.py:
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
"http://127.0.0.1:3000"
]
This makes it so that the frontend is allowed to make requests to your backend by using the Access-Control-Allow-Origin header.
If you need to pass along cookies (e.g. csrf token, credential tokens) with the request from your frontend to the server, additionally add the following line:
CORS_ALLOW_CREDENTIALS = True
Then, you would have to set up your request client on the frontend. I personally use axios:
const response = await axios.post(url, { ...data }, { withCredentials: true })
Related
The front-end app is built on ReactJs and development server is running on http://localhost:3000. The back-end API is built with Flask 2.0.2 and is running on http://localhost:5000
In app.py file, the CORS has been allowed as mentioned in the documentation like:
CORS(app, resources={r"*": {"origins": "*"}})
When I try to submit the login form I still get the following error:
if you Enables CORS on your backend api , it should work.
I don't think this is an issue with your react frontend application.
cors is a security measure put in by browsers.
You could bypass the Cross-Origin-Policy with chrome extension but it's not advisable -
Try this on your backend API:
Ensure you have flask cors installed
create a configuration dictionary like this
api_v1_cors_config = {
"origins": ["http://localhost:5000"]
}
You can then set a global cors for your app like this
CORS(app, resources={"/api/v1/*": api_v1_cors_config})
// this would allow all methods, origins
I have a React frontend and a DRF Backend. In the frontend, I am trying to use axios to refresh a JWT access token. The refresh token is sent with every request as an HttpOnly cookie. DRF's Simple JWT library is refreshing the access token. The frontend is hosted on Netlify, which is working, and I am using ngrok to tunnel the backend from my localhost to an https url.
Inside my backend settings.py, I have:
INSTALLED_APPS = [
'corsheaders',
...
]
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
...
]
CORS_ALLOWED_ORIGINS = [
"https://app.netlify.app", //this is not the actual url, but the format is the same
]
CORS_ALLOW_CREDENTIALS: True
However, whenever I connect to the backend, I get these errors:
XMLHttpRequest cannot load https://ngrokurl/api/token/refresh/ due to access control checks.
Origin https://app.netlify.app is not allowed by Access-Control-Allow-Origin.
Meanwhile, in the backend console, I see that the preflight OPTIONS request returns a 200 status:
[15/Jan/2022 17:47:25] "OPTIONS /api/token/refresh/ HTTP/1.1" 200 0
Not sure if that is anything to do with CORS though.
This is what I am getting:
Error: Image of errors
Request / response: enter image description here
I would greatly appreciate any help; I am quite new to all of this!
I noticed an error CORS_ALLOW_CREDENTIALS:True should be CORS_ALLOW_CREDENTIALS= True
I am implementing http proxy middleware in to my react app. I want to proxing qa or dev backend services urls from my local .
Example of my dev login url below
https://cors-anywhere.herokuapp.com/https://dev.sju.uk/auth/login
my setupProxy.js
module.exports = function (app) {
app.use('/auth/login' ,createProxyMiddleware({
target: 'https://cors-anywhere.herokuapp.com/https://dev.sju.uk/auth/login',
changeOrigin: true,
})
);
};
I started my app and click the login button and the request got failed with 404 not found error . Not sure why my target is not replacing with my actual http://localhost:9009/auth/login uri to https://cors-anywhere.herokuapp.com/https://dev.sju.uk/auth/login.
Also am not getting proxy created message in my console when we do npm start as well. I am using webpack dev server not react-scripts . If any changes required on webpack side or am i missing anything badly please let me know. I tried small poc it got worked but that is simple without herokuapp things.
It took me some time to understand how the http-proxy-middleware works.
Look at the following diagram from the http-proxy-middleware Docs
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
For simple configurations, any request that your front-end does calling an API get observed by a matching pattern on the path section of the above diagram and overwritten with your target configuration, to be exposed in the header of the request as a different URL. This also help you in the development phase locally to avoid the CORS blocking mechanism of the browsers.
Example:
Let's imagine we need to call from our front-end exposed at http://localhost:3000 to an endpoint located at https://localhost:7005/api/WeatherForecast
This type of calls will be blocked in all browsers by CORS.
So, with the following config, you will be able to bypass the cors problem.
const { createProxyMiddleware } = require('http-proxy-middleware');
const context = [
"/api",
];
module.exports = function (app) {
const webApiProxy = createProxyMiddleware(context[0], {
target: 'https://localhost:7005',
secure: false,
changeOrigin: true,
headers: {
Connection: 'Keep-Alive'
},
logLevel: 'debug'
});
app.use(webApiProxy);
};
With this, any request made from http://localhost:3000 will be intercepted by the proxy-middleware and if it finds a /api in some part of the path will be changed to https://localhost:7005/api and also concatenate the rest of your original path following the /api.
So finally, your front-end will be asking things from http://localhost:3000 but all the request will arrive to https://localhost:7005 as if they were request by https://localhost:7005 and this will fix the Cors problem coz your requesting and responding from the same origin.
I Guess your can fix your problem by writting your config this way:
module.exports = function (app) {
app.use('/auth/login' ,createProxyMiddleware({
target: 'https://dev.sju.uk/auth/login',
changeOrigin: true,
headers: {
Connection: 'Keep-Alive'
},
})
);
};
Bare in mind, this libray not only can help you with the CORS problem but also to perform hundred of things for any request/response like change arguments from the body, add things to the body, add headers, perform operations before the request aka logging what's requested, perform operations on the response aka logging again what has returned, etc, etc.
Hope this will help to resolve your issue!
I am calling a Django back-end api from React front-end using axios.
For that api which is login api, I am using Django Knox package in logic.
React.js - I am calling axios.request(method, url, data) and the api call is working correctly.
When I went to Developer tools>Network, I can see Referer header set to React.js website in request header and no other csrf-related header. In Response headers I can see two set-cookie headers, csrftoken and sessionid.
React Native - same way I am calling api but api returns error csrf failed referer checking failed - no referer . When I checked response.config, Referer header is not set unlike React.js
Curl - works fine
httpie - works fine
How can I get rid of this error.
Note 1 - My Django back-end is based on api token logic and not csrf in any way.
Note 2 - React.js and Django are hosted on different domains. I am facing error in React Native which is in debug mode.
Update 1 - After disabling CSRF middleware in Django settings.py, now I am getting only one setCookie header (csrftoken is no longer obtained) but same error still persists.
Django Rest api need a Referer header.
In case of React.js it is automatically set (maybe by browser) and its value is current website.
But in case of React Native, it is not set. so we have to manually set it.
From this link, i set Referer header in axios. see below code
export const axiosAPICall = (method,url,data,headers) => {
let request = {
method: method,
url: url,
};
if (data) {
request['data'] = data;
}
if (headers) {
request['headers'] = headers;
}
// Referer is auto-set in react.js as same website value.
// for react-native we have to set it manually to target api:port
request['headers'] = {
...request['headers'],
Referer: url
}
return axios.request(request)
.then(res => res.data)
.catch(error => {throw error});
};
In Django settings.py, I commented CSRF middleware
In Django settings.py, I added only TokenAuthentication class to remove SessionAuthentication.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
]
}
Note - Please do steps 2 and 3 at your risk after knowing your requirements properly. I removed CSRF middleware because my API was completely dependent on token for auth. I did not need CSRF in any way.
I am learning with Django and Angular.
I have setup a Django API back-end on on http://serverip:8666/athletics/
I have created a small Angular application that I am running from my local machine.
The following code in my Angular app:
$scope.list_athletes = function(){
console.log('hey');
$http
.get('http://serverip:8666/athletics/')
.success(function (result) {
console.log('success');
})
}
generates the error:
XMLHttpRequest cannot load http://serverip:8666/athletics/. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://127.0.0.1:65356' is therefore not allowed
access.
What causes this error? How can I resolve it so that I can access the Django API from my local Angular app?
The problem you're having is related to not having CORS enabled.
As a security policy, JavaScript can't make requests across domains while running in your browser. This is meant to prevent untrusted code from executing without the user's knowledge. The workaround is to enable CORS by white listing domains.
You need to set the Access-Control-Allow-Origin response header in your responses like so:
def my_view(request):
data = json.dumps({'foo':'bar'})
response = HttpResponse(data)
response['Access-Control-Allow-Origin'] = 'http://127.0.0.1:65356'
return response
This will enable CORS for your angular app. You can even add django-cors-headers to your project to have this functionality implemented for you. This can be added to any Django response object, such as django.http.repsonse.HttpResponse. Because you appear to be using a DRF Response object, you may need to use something like
return Response(serializer.data, headers={'Access-Control-Allow-Origin': 'http://127.0.0.1:65356'})
to set your response headers.
You should also check out this site for more information on how to enable CORS in your webapp.
Have you done the settings part in settings.py
INSTALLED_APPS = (
'corsheaders',
)
MIDDLEWARE_CLASSES = (
'corsheaders.middleware.CorsMiddleware',
)
CORS_ORIGIN_WHITELIST = (
'http://127.0.0.1:65356'
)
And also include CORS_ALLOW_CREDENTIALS, CORS_ALLOW_HEADERS settings