My Asp.Net5 Web Api is not working on Chrome, this is due to a CORS issue and seems that my CORS configuration is conflicting with my OAuthBearerAuthentication.
In my Startup.cs:
services.AddCors();
services.ConfigureCors(o => o.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()));
My controller looks like:
[Authorize(OAuthBearerAuthenticationDefaults.AuthenticationScheme)]
[EnableCors("AllowAll")]
public class MyController
Then I get No 'Access-Control-Allow-Origin' header is present on the requested resource.
However, if I remove the authorize attribute:
[EnableCors("AllowAll")]
public class MyController
Then I am allowed... What is going on?
You can just add the following into the system.webServer section of the web.config file:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT" />
<add name="Access-Control-Allow-Headers" value="accept, content-length, content-type" />
</customHeaders>
</httpProtocol>
Modify the methods and headers as necessary. You cannot use * in those headers. It will also allow you to request content like images and HTML with AJAX, not just controller action served resources.
First of all, clear cache on chrome, and try in edge. Chrome is eating your errors.
See the request, you should have 2.
PREFLIGHT and the request itself.
If preflight (OPTIONS) fails, the request is not even made.
Normally preflights fail because Server error 500. Exceptions does not include cors headers so this may be your issue here.
Ok, now, the problem is chrome won't show the error ANYWHERE.
So, you can inspect the request on EDGE, which will give you an actual error (you must use developer console, the error won't show on the browser) or use fiddler.
Now that you can see your error, you may probably know how to continue, but to add a little bit of what I faced myself:
If you have services.AddMvc(), this already adds cors to the pipeline, so adding it using services.AddCors() again throws a key already found exception. (I think it's a bug, may file an issue on github).
to configure cors when AddMvc is used you do like this:
services.ConfigureCors(options =>
options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
.AllowAnyMethod()
.AllowCredentials()
.AllowAnyHeader()));
to actually add cors to the pipeline, you need to do app.UseCors("AllowAll"); on Configure method.
if you are using app.MapWhen take care that MapWhen forks, so you may need to specify UseCors for all the branches you are using with MapWhen that need cors, like your api endpoints. (If you have no idea of what I'm talking about here, just ignore it.)
Related
I have a WebApi done with .net core 3.1. It's hosted in the IIS in my laptop. At the same time I developed an angular UI and published it in the same IIS. Same IIS but each application has it's own port. When I insert a new record from the ui, it is done successfully, meaning the POST is successful. If I try to modify it, meaning a PUT, It does not go through. Seeing the developer tools in the browser, the console displays a message saying the Access to XMLHttpRequest at 'http://blablabla.com:777/api/items/333' from origin [the web application url goes here which is something like http://blablabla.com:778] has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I have tried what I found in this website. Meaning that I modified the Startup.cs adding this in the ConfigureServices:
services.AddCors(options => {
options.AddPolicy(name: "Policy1", builder => {
builder.AllowAnyOrigin().AllowAnyMethod().WithHeaders(HeaderNames.ContentType, "Access-Control-Allow-Origin");
});
options.AddPolicy(name: "Policy2", builder => {
builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
});
options.AddPolicy(name: "Policy3", builder => {
builder.WithOrigins("http://name.com:7771").AllowAnyHeader().AllowAnyMethod();
});
});
and this in the Configure method (after app.UseRouting();):
app.UseCors("Policy2");
I have no idea about what else to try.
After some time of full of frustration with this problem I finally found a solution.
Having this problem when trying to update (PUT). I can insert (POST) without any problem.
Access to XMLHttpRequest at 'http://superinspections.com:8000/api/Cities/12962'
from origin 'http://superinspections.com:8001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
header is present on the requested resource.
Access to XMLHttpRequest at from origin has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Solution:
In IIS version 10:
click on the website you are having the access origin problem with (the back end) and double click on HTTP Reaponse Headers icon. Add the following entries:
Access-Control-Allow-Headers with valut *
Access-Control-Allow-Methods with value POST, PUT, GET, OPTIONS
Access-Control-Allow-Origin with value *
This will add the following to the web.config file of that site:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="*" />
<add name="Access-Control-Allow-Methods" value="POST, PUT, GET, OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
After running the progran I did not have the Access-Control-Allow-Origin problem but I had a new message: HTTP 405 Method Not Allowed.
To solve this I found the solution here:
Web API Put Request generates an Http 405 Method Not Allowed error
And tha solution was to remove the WebDAV module with the following entry in the web config files in both, front end and back end.
Place this inside <system.webServer>.
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/> <!-- add this -->
</modules>
and add this to the handlers section:
<handlers>
<remove name="WebDAV" />
...
</handlers>
After that, the application was working as expected. I need to add that I needed to keep the cors configuration in the Startup.cs.
In the ConfigureServices:
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.AllowAnyMethod());
});
And in the configure, between app.UseRouting() and app.UseAuthentication()
app.UseCors("CorsPolicy");
and the attribute [EnableCors("CorsPolicy")] in the controllers that may need it.
For what I need, which is development and testing of an Angular application, this is sufficient. You may play with the Cors configuration in the client in order to get rid of the server setup, as I will do when I complete the development. But the WebDAV part I think that is unavoidable.
One thing I need to add is that the web config changes go away if you republish your back end.
Any comments will be appreciated. Specially an explanation of what is WebDAV.
I realize that this question seems to come up frequently. I've gone through each one and tried many of the suggested solutions. One solution did seem to get me to a "working" state, but it does not seem like it addressed the actual underlying issue, but instead somehow worked around it. So, let me explain my scenario and what I've tried.
I'm writing an AspNet WebApi application that will be served up by IIS. My application is currently using convention based routing, as opposed to attribute routing. My application needs to handle CORS pre-flight requests (OPTIONS). I've installed the required Microsoft.AspNet.WebApi.Cors package, from Nuget. Below are the versions of the AspNet packages that I'm using:
<package id="Microsoft.AspNet.Cors" version="5.2.4" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.4" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.4" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Cors" version="5.2.4" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net461" />
Based on my reading, the Microsoft.AspNet.WebApi.Cors package is supposed to add support for handling CORS pre-flight requests. This means I won't have to add manual OPTIONS action methods, etc - the nuget package brings that for me. So, I've configured the package so that it enables CORS for all available controllers, based on a commonly referenced blog post. To my understanding, this should be all that is needed for my application to begin responding to OPTIONS requests. Below is my configuration for completeness sake - it shows that I also configure some other things:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var jsonMapping = new RequestHeaderMapping("Accept", "text/html", System.StringComparison.OrdinalIgnoreCase, true, "application/json");
var corsAttribute = new EnableCorsAttribute("*", "*", "*");
config.Formatters.JsonFormatter.MediaTypeMappings.Add(jsonMapping);
config.Services.Replace(typeof(IFilterProvider), new UnityFilterProvider(UnityConfig.Container));
config.EnableCors(corsAttribute);
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Lastly, I've seen some reference to some items in the web.config regarding the OPTIONSVerbHandler. Mine is left at whatever the default value is, which is shown below ...
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Finally, with all of these items in place, it appears that my application still fails to handle OPTIONS requests. Using postman, I simply send an OPTIONS request to any of my endpoints and regardless of endpoint I receive the following 405 response ...
Allow →POST
Cache-Control →no-cache
Content-Length →76
Content-Type →application/json; charset=utf-8
Date →Wed, 14 Feb 2018 20:50:14 GMT
Expires →-1
Pragma →no-cache
Server →Microsoft-IIS/10.0
X-AspNet-Version →4.0.30319
X-Powered-By →ASP.NET
X-SourceFiles →=?UTF-8?B?QzpcVXNlcnNccmNvbGVcRG9jdW1lbnRzXFZpc3VhbCBTdHVkaW8gMjAxN1xQcm9qZWN0c1xQb3J0YWwuUkVTVFxQb3J0YWwuUkVTVFxhY2NvdW50XGF1dGhlbnRpY2F0ZQ==?=
{"Message":"The requested resource does not support http method 'OPTIONS'."}
Here's some of the things I've tried to fix this:
I tried removing the OPTIONSVerbHandler from web.config, which seemed to make no change.
I tried explicitly putting EnableCorsAttribute on individual action methods and controllers, which seemed to make no change.
I explicitly put HttpOptionsAttribute on an action method, which seemed to fix the issue. This seems like the incorrect approach, though, as that attribute is for saying that action method is for handling OPTIONS requests, which is not at all what I want. I thought Microsoft.AspNet.WebApi.Cors package brings its own OPTIONS handler.
I tried switching to attribute-based routing, as opposed to the original convention-based routing. Didn't seem to change anything.
Does anybody know what could be causing this issue? It doesn't seem like my Microsoft.AspNet.WebApi.Cors package is correctly wired up, or doing anything. The response has no CORS headers in it. It looks like AspNet doesn't think it has any OPTIONS handler in place, despite me enabling it in my configuration.
I've seen this question asked in several other locations. Most answers focus on web.config hacks, custom filter attributes, other custom code, etc, as the solution. I want to mark what ended up being the solution in my scenario, which I believe to be many of the other folks' scenarios ...
The Microsoft.AspNet.WebApi.Cors package does indeed work and handle OPTIONS pre-flight requests. It only kicks into action when the appropriate CORS headers are present, though.
So, in my scenario, I was testing this using a tool, such as Postman. I was testing by sending explicit OPTIONS requests. Well, many of these tools don't send CORS pre-flight requests, and even then, when sending manual OPTIONS requests they do not include the required CORS headers that trigger the Microsoft.AspNet.WebApi.Cors functionality.
So, in the end, for me, there was no technical issue or bug, it was a lack of knowledge about how the nuget package works. When I switched back over to my JavaScript project, and made the request across origin, using fetch, the requests worked. Chrome sends the pre-flight OPTIONS, with appropriate CORS headers.
So, make sure you're testing using appropriate CORS headers, if you're using a tool like Postman!
This isn't a CORS issue per se. It's your web server not allowing OPTIONS requests. I realize this isn't an answer, but it should help you get on the path to narrowing it down some more.
I am attempting to implement CORS in my web API layer of a project and limit the domains that the API will allow requests from. I am using the app.UseCors() method in my Startup.cs to setup CORS globally:
new public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
SystemConfiguration config = base.InitializeWebApiConfiguration();
// add our Cors Policy
app.UseCors(new CorsOptions
{
PolicyProvider = new CorsPolicyProvider
{
PolicyResolver = context => Task.FromResult(CorsPolicyHelper.GetCorsPolicy())
}
});
var authorizeAttribute = new AuthorizeAttribute();
config.HttpConfiguration.Filters.Add(authorizeAttribute);
app.UseNinjectMiddleware(() => this._kernel.Value);
app.UseNinjectWebApi(config.HttpConfiguration);
InitializeMappingProfiles();
}
The CorsPolicyHelper simply sets up a CorsPolicy object with the settings for Headers, Methods, Origins, etc. which are:
-AllowAnyMethod = true
-AllowAnyHeader = true
-SupportCredentials = true
-PreflightMaxAge = 604800 (7 days)
-Origins: "https://example.dev.com", "https://example-ci.test.com", "https://example-qa.test.com"
The problem I have is CORS is working on my dev and CI servers, however, it does not work on my QA server. My request has the correct origin "https://example-qa.test.com" but the resposne header does not include "Access-Control-Allow-Origin", and I am getting back:
XMLHttpRequest cannot load https://services-qa.test.com/api/data/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://example-qa.test.com' is therefore not allowed access. The response had HTTP status code 500.
I'm not sure what the difference is between my dev, CI, and QA servers are. They should be the same. But is it possible there is a server setting I need to change on my QA server to make it work? Possibly something in IIS?
Try this in your Web API's web.config (this version is cut down, but I'm sure you can put it together).
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
So, it's working 2 out of 3. My understanding is that for a preflight request to be successful, your IIS site needs to be set to allow anonymous access. Check your IIS settings on all three boxes to verify.
It ended up being a different problem. The app.UseCors() method I described above does work to enable CORS globally. The problem was in a transform I had for my web.config for the QA environment. It was a problem with the connection to the server that gives me my identity token. Thanks for the suggestions though!
I'm using Angular and ASP.NET API. The issue I'm facing: when I add CORS in the API code, it works on Internet Explorer but does not work on Chrome and Firefox.
Here is the error:
XMLHttpRequest cannot load http://localhost:41028/api/values/abc. The
'Access-Control-Allow-Origin' header contains multiple values '*, *',
but only one is allowed. Origin 'http://localhost:44796' is therefore
not allowed access.
This is the code I added in the web.config file:
<system.webServer>
...
<httpProtocol>
<customHeaders>
<!-- Adding the following custom HttpHeader will help prevent CORS errors -->
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
...
</system.webServer>
In the WebApiConfigFile.cs file I added:
var CorsAttribute = new EnableCorsAttribute("* ","* ", "* ");
config.EnableCors(CorsAttribute);
I'm using CORS for the first time. Any help will be appreciated.
You are setting CORS twice. I think that is the issue.
Please remove any one CORS settings. You can either remove it from web.config or from WebApiConfigFile.cs.
Chrome and Firefox use what is called a pre-flight check using the "OPTIONS" verb.
So, you have to add "OPTIONS" to the allowed methods in the web.config. You also may have to add some code to the Application_Begin request, like this answer suggests:
Handling CORS Preflight requests to ASP.NET MVC actions
Here are some resources for CORS:
IIS hijacks CORS Preflight OPTIONS request
http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
All other solutions provided for webAPI. This solution is for when you using webservice(.asmx) as API
Remove 'Access-Control-Allow-Origin' details from either in Global.asax.cs file's begin_request function or in web.config. Because this setting must be in one place only
I got this issue because I put the app.UseCors after ConfigureOAuth. Change the order fix the problem.
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
ConfigureOAuth(app);
WebApiConfig.Register(config);
// Used to put this line after ConfigureAuth(app),
// app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
Here is the detail in my case:
At the beginning I got Origin is not allowed in 'Access-Control-Allow-Origin', when calling \token.
LSo I add the customHeader including 'Access-Control-Allow-Origin', 'Access-Control-Allow-headers', 'Access-Control-Allow-methods'. It fixed the \token request.
But then I got duplicate 'Access-Control-Allow-Origin' when calling detail api. There are a lot suggestions, such as this just couldn't fix.
I had the same issue. After I put the exact domain instead of * (see below), it worked for me.
var CorsAttribute = new EnableCorsAttribute("https://www.mywebsite.com","", "");
config.EnableCors(CorsAttribute);
I had the exact same error and the reason was that
"Access-Control-Allow-Origin: *"
header was already present in the IIS HTTP Response Headers list.
Example
Removing it from the list worked for me.
I am either getting a 400, 404, or 405 error attempting to query my Web API OData Service.
My remote service name is configured to:
var remoteServiceName = 'http://localhost:50056/odata/';
In my entityManagerFactory I have Odata set:
breeze.config.initializeAdapterInstance('dataService', 'webApiOData', true);
And in my datacontext I am calling:
var manager = entityManagerFactory.newManager();
return breeze.EntityQuery.from('Courses')
.using(manager).execute()
.then(success).catch(failed);
I am currently getting the error:
XMLHttpRequest cannot load http://localhost:50056/odata/$metadata. No 'Access-Control-Allow-Origin' header is present on the requested resource
I can access this path just fine in the browser. I've found several resources to suggest I need to set the httpProtocol in my web.config as follows:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="*" />
</customHeaders>
</httpProtocol>
But that just gives me a
XMLHttpRequest cannot load http://localhost:50056/odata/$metadata. The 'Access-Control-Allow-Origin' header contains multiple values
I have also tried to set these settings from IIS Express's applicationhost config file but that gives me the following:
Invalid HTTP status code 400
I have also heard that adding the following setting to WebApiConfig should work:
config.EnableCors();
But I see no effect, and alternatively I have tried:
var cors = new EnableCorsAttribute(origins: "*", headers: "*", methods: "*");
config.EnableCors(cors);
Which also has no effect. I don't see what else I could be missing as I've exhausted every resource I've found online.
I am using Visual Studio 2013 express and using IIS express.
I found my problem. I was using OData v4. Apparently datajs does not support OData v4 yet. Adding the following code in the WebApiConfig smoothed things out even further:
var cors = new EnableCorsAttribute("*", "*", "*", "DataServiceVersion, MaxDataServiceVersion");
config.EnableCors(cors);
Ahh. At the moment the Web Api implementation of OData is full of pot holes ... including but not limited to lagging data.js support.
I'm in touch with the OData team and hopeful we can make progress soon.
Do you really need OData? Unless you need to support open clients, it is much better to go straight Web Api.