Intermittent CORS issue with FastAPI deployed on Heroku - 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.

Related

Request to Spring Boot application via Cloudfront fails inexplicably with 403 status

When I navigate to web.mysite.com, a static SPA hosted in S3, it has an iframe which has a src of mysite.com/some/path, which is a Spring Boot MVC application in Elastic Beanstalk. Both are behind Cloudfront distributions for HTTPS. This path is handled in the application with a custom resource resolver. This loads successfully, but inside the iframe content there is a script tag looking for mysite.com/some/path/thatsdifferent, handled by the same resolver.
This second request fails with a 403 and I cannot determine why. Navigating to the failing mysite.com/some/path/thatsdifferent directly in my browser or using postman succeeds with a 200 status. The server is configured to allow requests from web.mysite.com through CORS configuration (and there is no CORS-related error message) and Spring Security is configured to permitAll any requests to /some/** regardless of authentication. There is no response body or error message beyond the header x-cache: Error from cloudfront.
If I navigate to the-beanstalk-env-url.com/some/path, it loads the html and then successfully loads the content from the-beanstalk-env-url.com/some/path/thatsdifferent.
Requests to a few different but similar paths succeed. Going to a path which definitely 100% does not exists returns a 404.
The server logs show that the request is being successfully handled and Cloudfront is returning reasonable responses to the client. Looking at the Cloudfront logs simply reports a 403, without any additional information.
Almost 100% of Cloudfront 403 error articles and questions involve S3, which is not the part which is failing here.
Changing the Cloudfront distribution Allowed Methods from GET, HEAD to GET, HEAD, OPTIONS causes the requests directly to mysite.com/some/path/thatsdifferent to begin failing with invalid CORS request, this was fixed by whitelisting the Accept, Authorization, Host, Origin and Referer headers. This did not fix the underlying error.
Adjusting the logging for org.springframework.security doesn't log any extra information when a failing request occurs, my application security configuration is not what is causing the error.
After replacing Cloudfront with a load balancer on my environment in Route 53, the scenario works as expected, so the problem is definitely in Cloudfront.
The solution was to switch the Cloudfront Origin Protocol policy from HTTP Only to HTTPS Only.
I don't know why this mattered from the script file and not the html file, but I decided to test it out when I discovered that if I tried to connect to the Beanstalk environment URL via https, Chrome was warning me that the certificate being used was setup for the domain that was served by the Cloudfront distribution that was causing trouble.

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).

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

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.

Exposing POST Endpoint on Elastic Beanstalk

I have a Chrome extension that needs to send data to a separate application I have running on Elastic Beanstalk via POST request. The POST endpoint itself is working fine via http, as confirmed using cURL.
However, given I am posting JSON data from a non-origin domain, the AJAX POST request is performed via https. This is causing the POST request to timeout, both from the Chrome extension and from cURL. I've done some research on how to change the CORS settings on the nginx server on Elastic Beanstalk, but I don't really know what I'm doing and kinda grasping at straws. How can I enable CORS on ELB/nginx?
NGINX instance working on EB machines are just proxying the request to your application and passing back the response to the client. You can set CORS headers in your application and that's it.

Access-Control-Allow-Origin issue in XMLRPC request

Am working in Mobile App develoment using HTML5 + Phonegap. Currently am working a mobile App using XMLRPC and its working fine. (Android and iOS)
I need to work the same application as a website in browsers. (using HTML5).
But when am trying to Run my application on website i am getting this error :
XMLHttpRequest cannot load 'Client' URL'. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost <http://localhost/>' is therefore not allowed access.
When am search experts says that use JSONP. But using same XMLRPC method can i work it ?
For example ;
For a Login purposes am using ;
$.xmlrpc({
url: 'http://clienturl/xmlrpc/common',
methodName: 'login',
params: [Database_name','user_name','Password'],
success: function(response, status, jqXHR) {
alert('success'); },
error: OnError
});
Its working fine as a Mobile Application.
But gets Access-Control-Allow-Origin cross domain issue when i am trying to run as a Website.
How can i fix this ?
By default the SOP (same origin policy) allows cross-origin requests, but it prevents receiving the responses of those requests. The Access-Control-Allow-Origin in your error message is a CORS (cross-origin resource sharing) header. It tells the browser that you allow reading the responses of a domain (your XMLRPC server's domain) by sending requests from another domain (your XMLRPC client's domain). So you have to send back CORS allow headers from your server if you want to call it with AJAX.
note: CORS won't work in old browsers.
Possible solutions:
If you call http://clienturl/xmlrpc/common from http://localhost then the
response.header('Access-Control-Allow-Origin', "*")
is one not so secure solution according to this: Origin http://localhost is not allowed by Access-Control-Allow-Origin
But you can always add another hostname (e.g. http://client.xml.rpc) for your client, for example by windows you can modify the hosts file and add a binding using the IIS server.
I don't recommend this solution, because it is a security risk with the allow credentials header.
Another more secure options is to make a list of allowed hosts, check from which host you got the actual request, and send back the proper header:
if (allowedHosts.contains(request.host))
if (request.host== "http://localhost")
response.header('Access-Control-Allow-Origin', "null");
else
response.header('Access-Control-Allow-Origin', request.host);
else
response.header('Access-Control-Allow-Origin', server.host);
This is the proper solution with multiple hosts, because if you allow credentials for *, then everybody will be able to read and write the session of a logged in user.
By http://localhost and file:/// IRIs you have to use the null origin. I am unsure about other protocols, I guess in the current browsers you have to use null origin by them as well.

Resources