Angular + Django: Sending POST request with cookies (CORS) - ajax

I'm developing an app using Angular for client side and Django for server side. During development I'm running Django in port 8000 for managing all API requests, and serving my client app using Angular CLI running at port 4200.
Sending GET requests to Django work w/o problems but when I try to send a POST request that includes some cookies with session information, it fails as the cookies are not included in the header.
I know that the source of this "problem" is the CORS issue [read more here] and that it won't be a problem in production as both client and server apps will be running in the same server and port, however I wonder how can I fix this situation at least for development.
I've tried using the django-cors-headers module with the options CORS_ALLOW_CREDENTIALSand CORS_ORIGIN_ALLOW_ALL set to True but it didn't work.
Any ideas?

Finally I managed to make all work.
I thought it was a problem of Django so I installed django-cors-headers module, however the "problem" is in the browser (actually is not a problem, it is a security issue, see [here][1]).
Anyway, I solved the problem using a proxy rule for my Angular CLI, as follows:
First, instead of sending my requests to http://localhost:8000/api/..., I send them to /api/ (i.e. to my Angular server running at port 4200).
Then I added a file in my Angular project called "proxy.conf.json" with the following content:
{
"/api": {
"target": "http://localhost:8000",
"secure": false
}
}
Finally, I added the flag "--proxy-config" to the Angular CLI server:
ng serve --watch **--proxy-config proxy.conf.json**
Now, all API requests are sent to the port 4200 and Angular internally redirects them to Django, avoiding the CORS problem.
Note: With this solution I didn't need anymore the django-cors-headers module.

Related

Intermittent CORS issue with FastAPI deployed on Heroku

I deployed a FastAPI based backend on Heroku and whenever I query the url via cURL or Postman, it works fine. However, when it queried from a chrome extension (built on React for Github), it throws
Access to fetch at '<API>' (redirected from '<API>') from origin 'https://github.com' has been blocked by CORS policy: 'No-Access-Control-Allow-Origin' header is present on the requested resource.
Funny thing is that the request runs fine for most of the time but when the server is not queried for about 10 mins, it first throws this error 2-3 times then the subsequent requests succeed.
From the frontend, Javascript fetch API is used to query the API with method & Content-type header.
To set up CORS policy on backend, I followed this CORS docs. Following is the snippet:
app = FastAPI()
origins = [
"https://github.com",
"http://localhost:8000" # dev
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
I am not able to understand if this issue is from frontend, backend or Heroku free dyno going to sleep. Thanks.
The request to your API is most likely coming from "Origin": "chrome-extension://..."
You can change your FastApi controller to
origins = ["*"]
That should give you a temporary fix.
As far as adding your specific Chrome extension to the allowed origins ...that's what I'm on here searching for lol.

Is it possible to proxy the html get request to /graphql from a create-react-app?

I have a create-react-app application in which I enabled the proxy by adding:
"proxy": "http://localhost:3001",
to my package.json. That's working well for API requests to /graphql, but when the web browser request /graphql (for the purpose of loading the UI to run queries) gets handled by the frontend and not proxied. Is it possible to also proxy it?
Same thing happens when I try to do OAuth by visiting https://localhost:3000/auth/facebook, the frontend handles it instead of the backend.
It is indeed possible to further customize the proxy.
First, when a web browser requests /graphql or /auth/facebook, it sends an Accept header that holds text/html (among others). The configuration of the CRA proxy specifically ignores requests with this header value:
The development server will only attempt to send requests without text/html in its Accept header to the proxy.
(emphasis in original text)
Luckily, you may override the default configuration and basically hook the proxy middleware to your liking. There are detailed instructions in the docs and even more so in the npm package docs, but the crux of it is:
app.use(
'/graphql',
createProxyMiddleware({
target: 'http://localhost:3001',
changeOrigin: true,
})
);

CORS request did not succeed

I have a problem when I want to create an authentication system using VueJs as the frontend (http://localhost:8080/#/login) and Laravel 5.6 as the backend. When I try to submit login form using the api login url http://127.0.0.1:8000/api/v1/login, I get the error message:
Cross-Origin Request Blocked: The Same Origin Policy disallows
reading the remote resource at http://127.0.0.1:8000/api/v1/login.
(Reason: CORS request did not succeed).
I don't know how to solve this problem.
Could anyone here help me to solve my problem?
NOTE : I have to install laravel-cors before
This is an old question, but I'll reply nonetheless.
For me this error was caused by a self-signed certificate. If you open developer tools, select the network tab, click the call that failed CORS you can see the security tab. Click it to open it. If a cert is giving you problems the text "An error occurred: SEC_ERROR_INADEQUATE_KEY_USAGE" should be visible.
To resolve this just go to the URL that gave you the CORS error, and accept the cert manually.
Cross Origin Resource Sharing is a mechanism that uses additional HTTP headers to tell a browser to allow the web application running on one origin (client) have permission to access selected resources from a server at a different origin.
Basically, your Vue app (http://localhost:8080) needs to be allowed access to your Laravel endpoint (http://127.0.0.1:8000/api/v1/login) This is to prevent me from hitting your Laravel endpoint from my malicious website and acting like an authenticated user.
Based on the docs, you need to add 'allowedOrigins' => ['*'], but that means you're opening up your backend to all requests. That's fine if it's a public API but in this context it doesn't sound like you want that. Instead, in this case it would be 'allowedOrigins' => ['localhost:8080'], so that your Vue app can consume your Laravel server.
You have to use either localhost or 127.0.0.1 for all the requests. In general in your code you should make calls to the server by just appending the URI to the current host, without re-adding the host and port in the URI string. If you load your page from a given host, for example 127.0.0.1 and then try to make an AJAX request to another host, for example www.host.com, the request gets blocked to prevent XSS attacks
It sounds like you are running this in dev mode via webpack currently? If that is correct and your workflow is that you are going to build the Vue application and have it co-reside with your Laravel backend then you just need to update config/index.js to have a proxyTable entry that forwards webpack requests to the correct dev Laravel backend server.
This would look something like this.
module.exports = {
dev: {
proxyTable: {
"/": "http://127.0.0.1:8000/api/v1/login"
}
}
}
There is additional information available on how this works; https://vuejs-templates.github.io/webpack/proxy.html
I was stuck with this error recently while I was trying to get one of our old websites hosted via Azure (App Services) up and running again.
Reason: CORS request did not succeed was the error showing in the browser console, however, it turned that for our case the URL mentioned in the CORS error doesn't exist anymore - its referring to the old https://******.azurewebsites.net service url we had (previous hosted in Azure - App Services).
So also check that the URL mentioned in the CORS-error is in fact working.
In my case the computer was not displaying the correct date and time. When I try to view the page I would get the "CORS request did not succeed." Once I updated to the correct time and date the page displayed normally.
I had to change the base URL of axios. I didn't notice it was https://, not http://
file: src\store\index.js
change the
axios.defaults.baseURL = 'https://127.0.0.1:8000/api'
to
axios.defaults.baseURL = 'http://127.0.0.1:8000/api'
Note: Make sure it's exactly same URL and Port. You can see that in terminal where you start the laravel application (php artisan serve).

How to make a cross domain request and send cookies with the request

I'm developing 2 applications for backend and frontend (spring mvc and angular4), i host the spring app on tomcat server using the http port (8080) and my frontend using the http port (4200) , the communication between both of the apps is made using json.
To identify the user i'm using a session cookie.
The problem is that i came to a cross domain issue because i use different ports for both of the apps, the cookie is not send when i make a http post request.
the only solution i found until now :
When i put the angular app inside the /src/main/webapp of my spring project, following this documentation , i dont have the issue and the cookie are automatically set but it's painful to do the previous steps everytime when i want to test something.
I thought also about some workaround like jsonp during the development process but i don't think this would be productive plus later on i need to execute some e2e testing.
Did anyone have an idea/example about how to make this cross domain...
Communication can be established via proxy.
Add in package.json "start": "ng serve --proxy-config proxy.config.json" in "scripts".
In proxy.config.json add:
{
"/api/*": {
"target": "http://server.com:8080",
"secure": false,
"logLevel": "debug"
}
}
So after some researches i came out with this solution :
in term of security and scalability of my backend service the best way is to use CROS, any other solutions like JSONP, Proxy is just a workaround and this will bring nothing because of the same-origin-policy followed by browsers
Following this documentation the scenario that will happens :
1) the browser will send an OPTIONAL request
2) the server will response with the allowed origin
3) if the our domain(the frontend domain/ angular app in my case) is verified the cookies will be automatically send in another request
the implementation that i made :
in the spring app :
//Some logic before this
if ("OPTIONS".equals(request.getMethod())) {
response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
response.setHeader("Access-Control-Allow-Credentials","true");
response.setHeader("Access-Control-Allow-Methods","POST");
response.setHeader("Access-Control-Allow-Headers","Content-Type");
response.setStatus(HttpServletResponse.SC_OK);
((HttpServletResponse) servletResponse).setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
return ;
}
// some logic after this
in the front app we can send the request using xhr like it's described in the attached link.

Is it possible to run webpack dev server and backend server on same hostname and port to avoid CORS?

I am running a backend Laravel API and a frontend Vue.js application.
Option #1 would be to set those two up as follows:
api.example.com => serving the API
app.example.com => serving the frontend appplication
However this gets you in all the trouble with CORS, OPTIONS preflight etc.
So in order to avoid that, I am planning on setting it up like this:
app.example.com/api => serving the API
app.example.com => serving the frontend appplication
So no more CORS problems, but since I am using Webpack I am running into issues in local development. Webpack dev server is serving the frontend at:
app.example.com:8080
So again, I am running into CORS when trying to access the API on port 80 :-(
Help! How can I set this up, so I don't have to deal with CORS yet being able to make use of the Webpack dev server and the Laravel (Homestead) API backend?
I assume it's not possible to serve both Homestead as well as Webpack from the same hostname and port. But is there any set-up that avoids CORS?
There is a way to avoid doing cors requests by using the proxy mechanism. Then you basically have the solution you described with app.example.com/api for the backend and app.example.com for the frontend. The webpack-dev-server takes your requests and forwards them to the configured backend. An exemplary configuration could look like that:
devServer: {
proxy: {
'/api*': {
target: 'http://app.example.com:8080'
},
},
},
Depending on how your backend is set up, you possibly need to have a look at the rewrite function to do some processing of the path before handing the request to the backend.
For more details, please see the webpack-dev-server docs at: https://webpack.github.io/docs/webpack-dev-server.html#proxy
If you want to run this stuff in production, then you will not use the webpack-dev-server but either set up the proxy configuration in the web server you are using (e.g. apache or nginx).
Related answer: CORS error on same domain?
Domain, subdomain and port needs to be the same, which basically means unless you are serving both the app and api from the same server, you need to take care of CORS. There is no escape from that.
Your webpack development environment can help you with your vue.js app only. It cannot do the server side of things. You will need your server on a different port. So you will have to set Access-Control-Allow-Origin:* for all your API requests.
Official reference: https://www.w3.org/Security/wiki/Same_Origin_Policy

Resources