I am facing issues enabling CORS support for a ASP.NET CORE application that is hosted using Google App Engine and the flexible environment.
Every AJAX request using the axios library results in the following error...
Access to XMLHttpRequest at 'https://api.[something].services/request'
from origin 'http://localhost:8080' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested
resource.
Here the configuration of CORS on the web api:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
options.AddPolicy("MyPolicy",
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
}));
// ...
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
System.Environment
.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS",
Path.Combine(Directory.GetCurrentDirectory(),
Configuration["GAE:Credentials"]));
}
else
{
app.UseHsts();
}
// ...
app.UseCors("MyPolicy");
app.UseHttpsRedirection();
app.UseMvc();
}
This type of CORS errors are usually obtained when a resource1 does cross-origin HTTP requests to another resource2 without the handler for resource2 returning an Access-Control-Allow-Origin: response header containing the value http://resource1.
With this in mind, the http header handler configuration needs to be appropriately set in the application App.yaml file which is deployed in App Engine. Most browsers use the XMLHttpRequest object to make a cross-domain request,taking care of inserting the right headers and handling the CORS interaction with the server.
All these information above apply to App Engine Standard and not the App Engine Flex environment. That is because CORS requests are disallowed by default on App Engine Flex. However you can allow CORS request by adding this "x-google-endpoints" to your API configuration documentation.
Related
EDIT
I've found out through the comments that I was querying the general S3 api instead of the specific buckets api. Doing that from a browser does not work and I got the error I reported here. In order to "fix" that, I simply switched to using the specific buckets API.
I used the same configurations, but instead I called the s3.upload method as in:
const uploadFile = (file) => {
const uploadParams = { ACL: "public-read", Bucket: config.bucketName, Key: file.name, Body: file };
s3.upload(uploadParams, function (err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.Location);
// setProfilePic(data.location)
}
})
}
I want to upload a file to S3 from my React app. I am using the "official" aws-sdk module, from following this tutorial: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/s3-example-creating-buckets.html#s3-example-creating-buckets-scenario
The problem is that I am getting a CORS error right in my first attempt to print my buckets:
import AWS from 'aws-sdk'
const config = {
bucketName: 'train-my-game',
dirName: 'profile', /* optional */
region: 'us-east-2',
accessKeyId: proccess.env.ACCESS_KEY,
secretAccessKey: proccess.env.SECRET,
}
AWS.config.update({ region: config.region, accessKeyId: config.accessKeyId, secretAccessKey: config.secretAccessKey });
const s3 = new AWS.S3({ apiVersion: '2006-03-01' });
const printBuckets = () => {
s3.listBuckets(function (err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.Buckets);
}
});
}
printBuckets()
This fails with the error:
Access to XMLHttpRequest at 'https://s3.us-east-2.amazonaws.com/' from origin 'http://localhost:3000' 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.
In the AWS, my bucket is configured with the following permission XML for the CORS configuration:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Does anyone know how to fix this?
Thank you
To put objects to a bucket, list objects in a bucket, retrieve bucket policies etc. you need to enable CORS on the target S3 bucket. Read the CORS documentation or see the example at awslabs/aws-js-s3-explorer.
You will not be able to invoke ListBuckets, however. The reason is that the ListBuckets call is made to an S3 service endpoint (s3.amazonzaws.com), not to an S3 bucket endpoint (bucket.s3.amazonaws.com) and you cannot enable CORS on the S3 service endpoint. So, ListBuckets will never work in a regular browser. Some browsers allow you to suppress CORS, but it's not normal browser operation. Obviously, if your app were to run outside of the browser, e.g. as a CLI or in Electron, then ListBuckets would work fine.
If you’d like to send Authorization headers, your server had better be configured to allow it. Set your server up so it responds to an OPTIONS request at that url with an Access-Control-Allow-Headers: Authorization header.
Cross-Origin-Resource-Sharing (CORS) is the mechanism that prevents a web app from running client-side code which makes requests to another web app. Imagine if Facebook could run some javascript and read the email you have in Gmail (because you're already logged in).
To address this, all browsers block javascript from one server from accessing any HTTP resources at any other url/ip unless that URL or IP explicitly allows (trusts) the site that javascript originate from.
In the case of many of the AWS SDK's you must explicitly configure what CORS headers you would like to send when interfacing with your AWS (S3 in this case) Resources.
See: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/cors.html
Replace the AllowedOrigin "example.org" with the FQDN of the server serving your react application.
So I have an angular cli app with Angular 4 talking to a new .NET Core API project. My environment is Windows 7 and the standard browser used in my organisation is IE 11 (so ultimately needs to work with this, however I want to develop in Chrome or FF as TypeScript / .map files don't work on Windows 7). It's an internal web application and we need to use Windows authentication. I created the .NET Core app with Visual Studio 2017 Community.
TL;DR My problem is that I continually get CORS errors in Chrome and FF, even after hitting the api and successfully returning data from the back end. The bizarre thing is that Chrome and FF successfully call the api when I don't enable CORS on the .NET side. When I try to enable CORS Chrome or FF don't hit the api at all. In either case the client code calls an error handler regardless of whether it can connect to the api or not.
So here's the .NET code I tried (although Chrome and FF both call the api without this). I created a CORS policy in Startup.cs\ConfigureSevices with AllowAnyOrigin and also tried the specific "http://localhost:4200" url (local server the app runs on). Also various combinations of AllowAnyMethod and AllowAnyHeader.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("MyPolicy",
builder =>
{
builder.WithOrigins("http://localhost:4200")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
//...
}
I added the CORS policy globally in Startup.cs\Configure.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseCors("MyPolicy");
// ...
}
I also tried adding it to the Controller directly as an attribue using [EnableCors]
[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class CustomerController : Controller
Here's the method on the controller:
// GET: api/customer/id
//[Authorize]
//[EnableCors("MyPolicy")]
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id)
{
var customer = await _customerService.GetAsync(id);
if (customer == null)
{
return NotFound();
}
string msJson = JsonConvert.SerializeObject(customer,
JsonCustomSettings.CustomJsonSettings);
return Ok(msJson);
}
I also read that I need to add the withCredentials option to the api call in Angular - here's the Angular code:
getContent(Id: number): Promise<Client[]> {
const headers = new Headers({'Content-Type': 'application/json'});
const options = new RequestOptions({ headers: headers, withCredentials: true });
console.debug('In getContent:' + id);
return this.http.get("http://localhost:13751/api/customer/"+id, options)
.toPromise()
.then(res => this.extractData(res))
.catch(this.handleError);
}
Results:
In Chrome and FF "this.handleError" always gets called. As I said Chrome and FF both call the api and return data successfully when I remove the CORS settings from the api.
When I add any of the CORS options on the .NET side in Startup.cs and / or on the controller and put a break point in the controller code:
no error in IE 11 (however I get other TypeScript errors and can't debug due to the lack of .map files on Windows 7)
Chrome or FF don't hit the api at all, both return CORS errors (see below for errors):
When I disable all CORS settings on the api side:
no error in IE 11
Chrome and FF both hit the api and data are returned from my service. However "this.handleError" is always called and I get the CORS errors in the browser / TS code when the call returns:
====
Chrome error:
XMLHttpRequest cannot load http://localhost:13751/api/customer/2518. Response to preflight request doesn't pass access control check: A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:4200' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
FF error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:13751/api/customer/2518. (Reason: CORS header 'Access-Control-Allow-Origin' missing)
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:13751/api/customer/2518. (Reason: CORS request failed).
====
So I really don't understand why I'm getting the CORS error in Chrome and FF when I can step through the code on the api side and data is returned to the client. (I also have the "Allow-Control-Allow-Origin" plugin for Chrome but this doesn't seem to make a difference).
Would be great if someone could shed some light on this.
Do you set the "Access-Control-Allow-Origin" header to the api response?
If not, here's a way of doing that:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseCors("MyPolicy");
// ... add api and other stuff
//Add a middleware which sets the header on the response
app.Use(async (context, next) =>
{
// Add Header
context.Response.Headers["Access-Control-Allow-Origin"] = "*";
// Call next middleware
await next.Invoke();
});
}
Cross origin requests are blocked by default because of the browser security policies. To allow CORS requests in Google Chrome install this plugin : https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?utm_source=chrome-ntp-icon
You will see an icon at top right corner of chrome. Turn on Cross origin resource sharing and then try it out.
I'm learning Angular 2. This is my service that's supposed to pull data from an ASP.NET Web api application.
#Injectable()
export class ExpenseService {
private _expUrl = "http://localhost:65400/api/expenses";
constructor(private _http: Http){}
getExpenses(): Observable<IExpense[]> {
return this._http.get(this._expUrl)
.map((response: Response) => <IExpense[]>response.json())
.do(data => console.log('ALL: ' + JSON.stringify(data)))
.catch(this.handleError)
}
//more here...
}
The above code is working fine in Microsoft Edge. However, in Chrome and FireFox, I'm getting the following error:
XMLHttpRequest cannot load http://localhost:65400/api/expenses.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:3000' is therefore not allowed
I've enabled CORS in my web api as suggested by many posts.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
//...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
//...
app.UseCors(builder =>
builder.WithOrigins("http://localhost:3000/"));
}
That didn't change the outcome. I'm still getting the same error in Chrome and FireFox while Edge is working just fine.
Thanks for helping
CORS is something that are enforced by the client, supported by the server.
CORS is there to help you as a user. It restrict the possibility for a client, like javascript on host google.com, to call a service on mydomain.com. This is a cross-domain call, which Chrome and FireFox does not allow. (Would assume that Edge also supported this). If you are hosting a service and client on some host and port, CORS is not used.
A service must define which host from a cross-domain is allowed. This can either be from all or from a specific host.
To allow access from all host do the following:
Configuration
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
}
Controller
[EnableCors("AllowSpecificOrigin")]
public class TestController : ApiController
If your service is a public service, be aware of the consequences.
You can read more here: https://learn.microsoft.com/en-us/aspnet/core/security/cors
I have an angular app that sends an http request to my Service Fabric Web API (deployed on a Secure Service Fabric cluster) like so:
$scope.request_headers = {
"Content-Type": "application/xml; charset=utf-8",
"Access-Control-Allow-Origin":"*"
}
$http({
url: "Service_Fabric_web_api_url",
method: "GET",
headers:$scope.request_headers
}).
then(function (result) {
console.log(result);
});
I've also enabled CORS globally in my web api startup class like so:
HttpConfiguration config = new HttpConfiguration();
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
When I run my angular app locally and try sending the http request, I still get this error:
XMLHttpRequest cannot load Service_Fabric_web_api_url. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:xxxxx' is therefore not allowed access. The response had HTTP status code 500.
I'm able to access my service directly from my browser with the same url.
Also, the same http request works when I tried deploying my Web Api on an unsecure Service Fabric Cluster with the same lines added to the startup class to enable CORS.
Why is this happening even though I've enabled CORS globally in my Web API and particularly when its on a secure cluster?
In your Startup.cs class, do you have this line? :
public void ConfigureAuth(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
}
There are also a couple NuGet packages associated with Cors:
<package id="Microsoft.AspNet.Cors" version="5.0.0" targetFramework="net45" />
<package id="Microsoft.Owin.Cors" version="3.0.1" targetFramework="net45" />
The CORS message is a red herring. If you look at the end of the error message you'll see this:
The response had HTTP status code 500.
Usually the response will include some detail about the error. I suggest using a tool like Fiddler with HTTPS decryption enabled so you can see the content of the response.
Using Chrome developer tools.I am getting a cancelled status on a request to a WEB API resource.(network tab)
Server : WEB API 2.1
Client: Angular $http request
The initial message referred to a CORS violation as the cause. I enabled CORS on the server.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//Going camel case in Web API http://frankapi.wordpress.com/2012/09/09/going-camelcase-in-asp-net-mvc-web-api/
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
// cors support
var cors = new EnableCorsAttribute( "http://localhost:9168/", "*", "*");
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
// To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
// For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
//config.EnableQuerySupport();
}
}
After CORS was implemented, I am still getting cancelled a response message on the API calls, however, when drilling into the message, the data is being returned from the server.
I checked Fiddler and the request header is passing the origin etc correctly, however I am still getting this error:
XMLHttpRequest cannot load http://localhost:4416/api/LookupTrades. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9168' is therefore not allowed access.
There seems to be loads of posts about the cancelled status in chrome, all with different causes. Not sure what to do next. Any ideas?
install a Nuget package `"Microsoft.AspNet.WebApi.Cors" (version="5.1.0")
Add following line in your WebApiConfig.cs file
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
you can also set this property in your js file before ajax call
$.support.cors = true;