How to enable CORS in Asp.Net MVC5 - asp.net-mvc-4

I am running Angular 6 in my local and getting CROS error when invoking MVC controller action method.
I tried to fix this by adding below line of code in my .net application's web.config file. But still getting same error.
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
I do not want to run a browser by disabling web security also I do not want to create a class since only to run in my local I need to enable the CORS.
Is there any simplest of way to fix this in Web.config or Global.asax file.

CORS requires 3 headers to work correctly.
A great resource for remembering how CORS works is The MDN Documentation.
The header you have included will allow all origins to make a request. But does not specify which requests they are allowed to make, and so, all requests are blocked.
To allow all origins to make specific requests you need to include the Access-Control-Allow-Methods header, which tells the browser which requests the web server is allowing on that endpoint.
Depending on how your requests are formed, you may also need to include the Access-Control-Allow-Headers header, which tells the browser which headers it is allowed to send to the web server on that endpoint.
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
Using all this, the correct configuration for your web.config would be:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Methods" value="GET,POST,OPTIONS"/>
<add name="Access-Control-Allow-Headers" value="Content-Type"/>
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
Which will allow you to access that endpoint using either POST or GET.
The Access-Control-Max-Age header will tell your browser to cache these results for that many seconds, for performance reasons.
Also please be sure to not include this configuration in any production system you may be running.
It's always best to enable CORS explicitely for each action / controller that may need it.

Adding below code to Application_BeginRequest at Global.asax worked for me:
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost:7777/");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
//These headers are handling the "pre-flight" OPTIONS call sent by the browser
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, GET");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "content-type");
HttpContext.Current.Response.End();
}
Use desired urls , Methods and Headers
Also There is no need to change anything in Web.config

Related

How to enforce HTTPS only (no redirect, block HTTP) on Azure App Service / Web App

Microsoft's own documentation on HSTS says the following regarding HSTS, HTTPS redirection, and APIs:
Web APIs should either:
Not listen on HTTP.
Close the connection with status code 400 (Bad Request) and not serve the request.
…
… a single authenticated call to an API over HTTP has risks on insecure networks. The secure approach is to configure API projects to only listen to and respond over HTTPS.
My takeaway is: APIs should not redirect, since clients may happily send sensitive data over HTTP and everything "just works" due to the redirection. Even for browsers and when using HSTS, the first request (with potentially sensitive data) may be done using HTTP. Instead, APIs should fail HTTP requests and respond only via HTTPS.
After having spent the better part of the day researching this, I find that in Azure App Service / Web App, there seems to be no simple way to follow these recommendations. Regardless of whether "HTTPS Only" is On or Off, the API can be called via HTTP: If On, it redirects to HTTPS, and if Off, it's fully available with HTTP without redirection. One would think there'd be a simple way to make the app service / web app listen only over HTTPS. For example if the "HTTPS Only" button was Off/Redirect/On.
The documentations says that:
To disable HTTP redirection in an API, set the ASPNETCORE_URLS environment variable or use the --urls command line flag. For more information, see Use multiple environments in ASP.NET Core and 5 ways to set the URLs for an ASP.NET Core app by Andrew Lock.
Unfortunately, neither of these two links describe whether this is relevant for App Service / Web App, or what the environment variables should be. I have not been able to get it to work. It also seems that this would require duplicating any custom domains, forcing you to remember to keep the environment variable in sync with changes to custom domains.
How can I make Azure App Service / Web App listen only on HTTPS?
My current workaround is to deploy the following web.config which, ironically, requires "HTTPS Only" to be Off for the HTTP request to reach the app service and be rejected. However, it does do the job of ensuring that no HTTP-only API clients will be developed, since they simply won't work from the outset.
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Disable HTTP" enabled="true" stopProcessing="true">
<match url="(.*)" ignoreCase="false" />
<conditions>
<add input="{HTTPS}" pattern="off" />
<add input="{WARMUP_REQUEST}" pattern="1" negate="true" />
<add input="{REMOTE_ADDR}" pattern="^100?\." negate="true" />
</conditions>
<action type="CustomResponse" statusCode="400" statusReason="HTTPS Required" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
(Conditions from this blog post.)
If anyone has a better, simpler, or more official method, I'll gladly accept that answer. Also, I'm not sure the the WARMUP_REQUEST part works (copied from elsewhere); if I change CustomResponse to AbortRequest, the slot swap operation fails because the warmup requests are dropped.

Redirect Response always redirects to the same domain

I'm writing a suite of ASP.NET Core web applications that occasionally have to redirect to one another. When testing locally, everything works fine. However, when I publish them on our staging server, the redirects always "stay" in the same host. For example, if I am on http://app1.test/ and redirect to http://app2.test/somepath, what I actually get in the Location HTTP header i http://app1.test/somepath: any URL I specify is transformed so that it "stays" in the current host name.
This doesn't happen locally, however. I've deployed the apps as Kestrel processes, and they are exposed via IIS working as a reverse proxy. May this be the cause? What should I do to fix the issue?
UPDATE
Here is the full web.config for the reverse proxy of app1.test:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://localhost:5000/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
<system.web>
<sessionState mode="InProc" />
<customErrors mode="RemoteOnly" />
</system.web>
</configuration>
app2.test's web.config is virtually the same (apart, of course, for the port numbers).
UPDATE 2
I'll try to explain better. I noticed that the target site doesn't really matter, so I'll keep things simpler: I have an action in my application that I want to redirect the user to Google. This is the action, in the Home controller:
public IActionResult ToGoogle()
{
return Redirect("https://www.google.com?q=Hi");
}
If I launch the web app locally and request http://localhost:1234/Home/ToGoogle, everything is fine: the response is a 302 Found, with the correct URL (www.google.com etc.) in the Location header.
Once I publish the app to the staging server (Kestrel app on port 5000, behind an IIS reverse proxy with the rewrite rule posted above), this is what happens instead:
What is the cause of that?
I found the solution myself. It was indeed a problem with reverse proxy.
IIS has an option to rewrite the host in response headers. The solution is described in this answer (there are addenda in other answers to that same question if your version of IIS or Windows Server is not the one specified).

WithOrigins partially overrides Access-Control-Allow-Origin .NetCore API

In my Startup.cs I have
app.UseCors(builder => builder.WithOrigins("https://acme.com"));
In my web.config I have
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Accept-Encoding" value="gzip, deflate, sdch" />
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="Origin..." />
When I submit an ajax request like this it tells me I that ACAO only allows one value, I have multiple "https://acme.com, *".
When I remove the values section completely, same error, but instead of listing my origins, it starts listing the values from the Allow-Access-Control-Headers tag.
When I remove the ACAO tag completely, it understandable tells me there is no tag.
What is the ACAO tag supposed to look like if I have a WithOrigins specification in my config?
The question isn’t clear about what origins you actually want to allow. It seems your choices are:
If you want to allow just https://acme.com, then you can drop the <add name="Access-Control-Allow-Origin" value="*"/> line from your web.config and the server will still send an Access-Control-Allow-Origin: https://acme.com response header.
If you want to allow all origins, app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll) is what you want to use instead—and that case too you want to also drop just the line with
<add name="Access-Control-Allow-Origin" value="*"/> from your web.config, since the server will already send an Access-Control-Allow-Origin: * to allow all origins.
You can also specify the allowed headers in your app.UseCors call, like this:
app.UseCors(builder => builder.WithOrigins("https://acme.com")
.WithHeaders("Authorization", "Location"));
Note that you shouldn’t need to specify the Origin header there, because browsers don’t require Origin to be in the Access-Control-Allow-Headers in order for it to be allowed. (Because the Origin header is set and sent by the browser itself in requests; it’s not a “custom” header.)
If you just want to allow all request headers, you can instead do this:
app.UseCors(builder => builder.WithOrigins("https://acme.com")
.AllowAnyHeader());
If you use either .WithHeaders(…) or .AllowAnyHeader() headers there, you can then also drop the <add name="Access-Control-Allow-Headers" value="Origin..."/> line from web.config
This was actually someone else's project, so I'm not sure where the web.config entry came from to begin with. I deleted the <httpprotocol> section of the web config entirely and got the AddCors() to work by using the normal process of:
app.UseCors(builder =>
{
builder.WithOrigins("http://acme.com");
});
It seems as though having an <httpProtocol> tag in the web.config was causing it to look in a two places for information that was only supposed to be present once.

How to geenrate or customise http headers

I am using AzureReader2 for resizing image that I request from azure blob, resizing is working fine.
Below is my code which is enough for the resizing the image from azure using AzureReader2 plugin
<resizer>
<plugins>
<add name="MvcRoutingShim" />
<add name="AzureReader2" connectionString="DefaultEndpointsProtocol=https;AccountName=xxxxxx;AccountKey=xxxxxxx" endpoint="http://xxxxxxx.blob.core.windows.net/" />
</plugins>
<clientcache minutes="2880" />
</resizer>
But I want to customize http headers like ETag, Last-Modified, Cache-Control options via my webCofig file configuration settings. Which I am feeling difficult to proceed.
So, Any pointers or workaround or leads for generating and customizing the above mentioned options.
You're using IIS, so use IIS' built-in support for cache control.
See IIS7 Cache-Control
With disk caching, IIS typically overrides any cache headers ImageResizer sets (like the Expires header set via 'minutes'), so there's not much it can do anyway.

CORS settings being ignored, Access-Control-Allow-* headers not being written

After running into the famous Access-Control-Allow-Origin problem while testing ServiceStack, I did a bunch of reading on CORS to better understand the problem. I also came across this very helpful SO question.
However, the solutions there did not work for me. I tried including the CorsFeature plugin and also setting the endpoint config manually, but after trying both ways I saw that the response headers coming back from the server did not include any of my Access-Control-Allow-* headers, hence the problem remained.
I tried another solution which ended up working for me (through with some other problems that aren't relevant here). I added the following to my service's web.config:
<system.webServer>
[...snip...]
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
(Other readers, note that this only works on IIS7+. See http://enable-cors.org/ to learn more about enabling CORS on other servers)
My question is: why was I able to get my headers written using this web.config method, but not by using ServiceStack's built-in CORS support? Is there a config setting I'm missing somewhere?
I was reviewing more of #mythz's SO answers and came across this one. For reasons I don't fully understand (yet), adding in that request filter (as well as the CorsFeature plugin) allowed everything to work as expected. I don't get an error on my preflight OPTIONS request, or any origin errors on my GETs and POSTs.
So, in short, my final solution was to copy the code from mythz's answer in that post into my AppHost.Configure(), and remove my web.config custom headers. (Before I removed my custom headers from my web.config, I was actually getting my headers doubled up!)