Manage CORS between Google App Engine & Google Cloud Function - express

I'm trying to set up a new instance of a simple App Engine which communicate with a backend-function hosted on Google Cloud Function. The App Engine is protected with IAP, and the Google Cloud Function is private only. The GAE use Angular Framework and GCF use Node 14 with Express
.
I can't access to my GCF from the App Engine because the requests are blocked by CORS.
Access to XMLHttpRequest at '' from origin '' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I tried the popular solutions on the web :
Use the cors librairie on the GCF. So I had on my GCF
var cors = require('cors')
app.use(cors(cors({ credentials: true, origin: true })))
And I also add this line for every request
res.set('Access-Control-Allow-Origin', '*')
Add the http-header on my app.yaml
handlers:
- url: /(.*\.[A-Za-z0-9]{1,4})$
static_files: dist/\1
upload: dist/(.*\.[A-Za-z0-9]{1,4})$
http_headers:
Access-Control-Allow-Origin: "*"
- url: /(.*)$
static_files: dist/index.html
upload: dist/index.html
http_headers:
Access-Control-Allow-Origin: "*"
But I still get the same error message.
EDIT : so the first problem was due to an authentication issue, that why the error have the same response. So I decided to deploy the 2 apps on App Engine to simplify communication between the 2 services.

You can now have full access to the HTTP Request/Responses by setting
the appropriate CORS headers as per this documentation.
Just so you know the reason for the error you are facing, it is
because when your web browser is calling a service that is in a
different/cross domain, it doesn’t make a HTTP request right away, it
rather starts with making an OPTIONS request( a preflight request)
and compares the value of Access-Control-Allow-Origin header in the
result with the current domain i.e. it checks for this (req.method
=== 'OPTIONS') in the headers and if the header value matches the host, the actual call is made, otherwise the action is stopped and
the error as the one above is thrown.
To have a thorough understanding of the above concept, have a look at
this stackoverflow answer and read this article for more insights.

Related

How to stop 'CORS missing allow origin error' when deploying Express application using Serverless Component?

When my React frontend calls my Typescript Express REST API (hosted on API Gateway using Serverless Components), I get the following error:
Access to XMLHttpRequest at 'https://randomId.execute-api.ap-southeast-2.amazonaws.com/userLoginSignup' from origin 'https://www.tueshey.com' 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.
My app.ts CORS config is like this (for reference, here's my whole file):
...
const app = express();
// CORS
const allowlist = ['https://www.tueshey.com'];
const options: cors.CorsOptions = {
origin: allowlist,
};
app.use(cors(options));
...
When I inspect the request locally, there is an OPTIONS request that returns first that includes the Allow Access Origin header but not when I deploy it. It is working correctly locally.
you will have to enable CORS on API Gateway as well. When click on the resource endpoint on API Gateway, on actions there is Enable CORS. That will add Options method also for your resource. If you want some customization you will have to add OPTIONS method manually

CORS policy blocking POST requests to API

I'm trying to deploy an app I created online. The UI is created using vue.js and it's calling a API written in dotnet core. I'm running dotnet core 2.2.
The web project and the API are on different servers and accessible under different domains, the web project is hosted on Netlify if that makes a difference. I managed to set up the CORS policy so that locally everything worked fine. When I access the app on the webserver I receive CORS errors whenever I post data. My GET and DELETE requests work just fine.
Here is my CORS policy
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("Default", builder =>
{
builder.WithOrigins(/* the domain where my web project is hosted */);
builder.AllowAnyMethod();
builder.AllowAnyHeader();
builder.AllowCredentials();
});
});
}
So I'm thinking everything should be fine. AllowCredentials is required because I'm using SignalR which otherwise wouldn't work.
The error message in the dev tools is
POST [my api endpoint] 400 (Bad Request)
Access to XMLHttpRequest at '[my api endpoint]' from origin 'https://xxx.netlify.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
And when I look into the console where my dotnet project is running I see the following error message
Connection id "0HLQNTR19GE1T" bad request data: "Requests with 'Connection: Upgrade' cannot have content in the request body."
Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Requests with 'Connection: Upgrade' cannot have content in the request body.
at Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException.Throw(RequestRejectionReason reason)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1MessageBody.For(HttpVersion httpVersion, HttpRequestHeaders headers, Http1Connection context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.CreateMessageBody()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequestsAsync[TContext](IHttpApplication`1 application)
So far I tried setting the Access-Control-Allow-Origin = "*" Header via the netlify.toml file, using the [EnableCors] attribute on my controller action. I edited my AJAX request (axios) and set withCredentials: true and in general played around with the CORS policy a lot. Unfortunately without luck and I'm running out of ideas.
I'm happy about any suggestions.
Check your nginx.conf file for a line called proxy_set_header and set it to Connection $http_connection

how to skip Preflight Requset in vue with content-type:application/json

error :"405 not allowed Method" in post method type call in request command vue
i need call api function with content-type:application/json and post Method type with request command in vue ,but browser add preflight request with options method type and it causes this error :"405 not allowed Method"
var options = {
method: "POST",
url: "http://api.sample.com/login",
headers: {
"Access-Control-Request-Method":"POST",
"cache-control": "no-cache",
"content-type": "application/json",
},
body: '{ Username: "demo", Password: "demo", Domain: "test" }'
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
body.data;
alert("ok");
});
The OPTIONS call is done whenever you do a cross-origin request. This means the domain your application is running on is different from the domain where the api is. A pre-flight request is mandatory for these requests, because the browser needs to figure out if you are allowed to do these requests. A 405 error means that the server thinks you are not allowed to make that request.
To solve this problem you can move your api to the same domain as your frontend. Please note that it cannot be on a subdomain.
A different way of solving this, is by sending back the correct headers. In your case you seem to at least miss the Access-Control-Allow-Methods response header. Make sure to send this header and either dynamically figure out which methods are allowed, or do something like the following. That would allow the most common methods to work.
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
In the comments you said that you do not have control over the api, and as such cannot change the response header. In that case your best bet is to contact whoever maintains the api and ask how to best use their api.
In the comments you said that this worked fine when you did the same thing in ASP.NET. ASP.NET is a server-side language, which means that requests in that context do not have a concept of "cross-origin". Cross-origin only comes into play in the browser, where the application runs on an actual domain.
Assuming you can set up a proxy on your application domain, you can also create a proxy that proxies all requests to the api you actually want to communicate with. You would deploy your domain on https://example.com and do your requests to https://example.com/api/endpoint. Your proxy will listen for requests that begin with https://example.com/api and proxy it to https://whatever.the.api.is/ with the appropriate endpoint and data.
Please keep in mind that while some api's might just be configured incorrectly, a lack of cross-origin response headers might just mean that the api is nog meant to be consumed through the browser. Part of this could be that the request contains a secret that should not be exposed to users that use your application, but should instead only be on the server. Using a proxy in that case would set you up for impersonation attacks, because you would expose the secret to your application, but defeat the cross-origin headers by making it appear to the application that the api is on the same domain.

Option request fails with 404

I am trying to send a GET request from my frontend to an API application. Both are running on my local machine. This is how it's built right now:
backend <===> frontend <=x=> API application
All three parts are running independently from each other in their own docker container and are only communicating with each other via HTTP-requests.
As shown in the top image, the connection between backend and frontend works fine, but between frontend and API application does not.
The stack consists of:
frontend: Node server with vue-js and for requests I use axios
API application: Scala with Play Framework 2.5.14
The API application itself works just find when I send a request to her via curl like this:
curl -X GET api-application.docker/api/user?userId=1 \
-H "Authorization: key" -H "Accept: Application/Json"
But when I call it from frontend, I get a 404 on the OPTIONS call. It also gives me a warning in Firefox related to CORS header Access-Control-Allow-Origin:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the
remote resource at http://api-application.docker:9000/api/user?userId=1
(Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
Therefore I first went into the api application's application.conf and added
play.filters.cors {
allowedOrigins = ["*"]
}
I also tried to exchange the asterisk for http://frontend.docker:8080
This didn't work, so I deleted that entry again and added this line instead:
play.filters.disabled += "play.filters.cors.CORSFilter"
Still no change at all. Now I am wondering if I misunderstood the connection between OPTIONS and CORS? Or did I turn it off wrong? Can anyone help me out?
EDIT:
More stuff I tried while waiting for answers, all without success:
I changed the entry in application.conf to:
play.filters.cors {
allowedOrigins = null
}
404 on OPTIONS request indicates your CORSFilter is not enabled. Since you are using Play 2.5 you can enable it by adding
libraryDependencies += filters
to your build.sbt, and by creating the following app/Filters.scala file:
import javax.inject.Inject
import play.api.http.DefaultHttpFilters
import play.filters.cors.CORSFilter
class Filters #Inject() (corsFilter: CORSFilter)
extends DefaultHttpFilters(corsFilter)
By default everything is allowed so there is no need to modify application.conf until you decide to start locking down access. You should NOT add play.filters.disabled += "play.filters.cors.CORSFilter" as this disables CORS support.
The reason why your curl request works fine is because non-browser HTTP clients do not enforce Same-origin policy (see related SO answer), thus CORS does not apply in the case of curl.
404 on OPTIONS request means that the following route is not found:
OPTIONS api-application.docker/api/user
The browser automatically sends this preflight request before sending the corresponding GET request. This OPTIONS route will be automatically taken care of by Play's CORS support once enabled.

Implementing Okta in React Native and get: Response to preflight request doesn't pass access

I'm implementing the Okta signin widget with React Native
I get this:
Failed to load https://dev-827074.oktapreview.com/api/v1/sessions/me: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
After trying to login, I get the following:
UnsupportedBrowserError {name: "UNSUPPORTED_BROWSER_ERROR", message: "There was an error sending the request - have you enabled CORS?"}
We've received similar errors from Okta. What we had to do is add the hostname for the server that hosts the webview as a Trusted Origin.
API -> Trusted Origins -> Add Origin
You can add multiple origins, you probably need to add http://localhost:3000.
You may need to add http://localhost:3000/implicit/callback to your app's Login Redirect URI's in the General Settings of your Okta app
The API you have written does not support CORS. CORS or Cross origin resource sharing allows a web app to submit requests to an API belonging to a different domain. This setting should be enabled on the API side.
This is how it works, whenever a request is sent to a different domain, an OPTIONS method is sent to the server. The server responds back with available options for the web app. If the verb is supported, the browser will send the actual request with the appropriate verb or method (For example, GET or POST). If the verb is not supported, you get the above error message.
In short, enable CORS for your API. If it is a Node / Express API it is just a simple cors package you need to add to your project and use.