I have an Express API running on IIS with iisnode. I have only Windows Authentication enabled and can send GET requests.
POST requests however return "401 Unauthorized: Access is denied due to invalid credentials."
I include credentials in the React fetch request:
await fetch("https://website", {
method: "POST",
credentials: "include",
headers: etc..)
and in my Express code:
app.use(cors({ origin: "https://website", credentials: true }))
I have the CORS module installed and in my web.config I have:
<cors enabled="true">
<add origin="https://website" allowCredentials="true">
<allowHeaders allowAllRequestedHeaders="true" />
</add>
</cors>
I also have in my web.config:
<system.web>
<authentication mode="Windows"/>
<authorization>
<add accessType="Allow" verbs="GET, OPTIONS, POST, PUT" users="*"/>
<allow roles="*" users="*" />
<deny users=?" />
</authorization>
</system.web>
I have tried removing "WebDAV" but that did not work. I also have set "ExtensionlessUrlHandler-Integrated-4.0" to allow all verbs. My web.config contains all the necessary code to make iisnode work, which I have not included in the post. I also tried adding a "allowMethods" tag inside the CORS tag but that did not work.
Any ideas on why my GET and OPTIONS requests validate correctly, but my POST requests get blocked? A solution should not include enabling "Anonymous authentication" because that is not an option.
I resolved the issue by removing the <add accessType="Allow" verbs="GET, OPTIONS, POST, PUT" users="*" /> line from within authorization.
Related
I have a .net core 5.0 web API which I am hosting on IIS. The front end is in Angular and is used for all the API requests.
Based on the documentation I have read to enable CORS, I have configured my startup.cs as below :
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors(options =>
options.WithOrigins(Configuration["ApplicationSettings:ClientURL"].ToString()
).AllowAnyMethod()
.AllowAnyHeader());
<other stuff>
public void ConfigureServices(IServiceCollection services){
services.AddCors();
}
and here's my appsettings.json file :
"ApplicationSettings": {
"ClientURL": "http://localhost:4200"
}
This configuration works as expected when I run the server through VS. But when I host this application in IIS, I get the error below :
Access to XMLHttpRequest at 'http://localhost:91/api/User/Login' from origin 'http://localhost:4200' 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.
According to the documents on Enable Cross-Origin Requests (CORS) in ASP.NET Core by Microsoft, this should be enough. However, I still configured the web.config on the server hosting IIS as below :
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS,PUT,DELETE" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
</customHeaders>
</httpProtocol>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\WebKeyMaster.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
</system.webServer>
</location>
</configuration>
But this doesn't help my case either. Can someone please tell me if there's anything wrong with my configuration?
I suggest you could check your middleware's order to make sure the Calls the UseCors extension method and specifies the _myAllowSpecificOrigins CORS policy. The call to UseCors must be placed after UseRouting, but before UseAuthorization.
For more information, see Middleware order.
I'm trying to allow CORS over a site, using the IIS CORS module (https://www.iis.net/downloads/microsoft/iis-cors-module), but I'm having troubles.
This is my web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="https://my.site" allowCredentials="false" maxAge="120">
<allowHeaders allowAllRequestedHeaders="true"></allowHeaders>
<allowMethods>
<add method="GET" />
<add method="POST" />
<add method="PUT" />
</allowMethods>
</add>
</cors>
</system.webServer>
</configuration>
with this setup, the OPTIONS (pre-flight) request works fine, but any further request (GET, POST) raise a browser exception because of missing Access-Control-Allow-Origin
I tryed to add the following to web.config:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="https:/my.site" />
</customHeaders>
</httpProtocol>
but in this way the OPTIONS fails because there're 2 instances of Access-Control-Allow-Origin
Using only custom header the pre-flight fails with code 500 (I think IIS doesn't support OPTIONS method without the CORS module).
IIS CORS module documentation is very poor and googling I only find info related to .NET code, but it's not my case. I can't modify code (and it's not .NET), I need to act on IIS.
How can I make IIS respond properly to CORS requests ?
From the code you have posted, it looks like you have not added your origin correctly.
The origin line should contain a (Fully Qualified Domain Name) FQDN or some regex that matches it.
A correct line would look like:
<add origin="https://my.site.com" allowCredentials="false" maxAge="120">
You can allow subdomains of your domain using:
<add origin="https://*.site.com" allowCredentials="false" maxAge="120">
From the sounds of it, you aren't receiving the headers you want back from the web server. This may be due to the webserver Only returning CORS safe headers.
Using the IIS CORS Blog from Microsoft, I've added in config that will expose the headers back in the request.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="https://my.site" allowCredentials="false" maxAge="120">
<allowHeaders allowAllRequestedHeaders="true">
<add header="DNT" />
<add header="Host" />
<add header="Origin" />
<add header="Referrer" />
<add header="User-Agent" />
</allowHeaders>
<allowMethods>
<add method="GET" />
<add method="POST" />
<add method="PUT" />
</allowMethods>
<exposeHeaders>
<add header="DNT" />
<add header="Host" />
<add header="Origin" />
<add header="Referrer" />
<add header="User-Agent" />
</exposeHeaders>
</add>
</cors>
</system.webServer>
</configuration>
However, according to This CORS documentation OPTIONS requests don't get the Allow Headers or Expose Headers configuration applied to them. Hopefully that's not the issue here though.
Below I've added the most basic CORS request I can think of. If this request works, then it may be a client side problem you are encountering.
fetch('example.com', {
method: 'GET',
mode: 'cors',
credentials: 'include',
headers: { 'Authorization': authString }
}).then(
response => response.json()
); // parses JSON response into native JavaScript objects
I have both my web and api projects deployed to separate Azure webapps and am struggling with a CORS issue. When deployed locally everything works fine, but not once published to Azure.
I am using two different methods to enable CORS and neither seem to be solving my issue.
Potential Fixes:
In my web.config I add a customHeader for <add name="Access-Control-Allow-Origin" value="*" />
In the Register method of WebApiConfig.cs I call enableCors as var cors = new EnableCorsAttribute("*", "*", "*"); config.EnableCors(cors);
The scenarios, referencing the above two fixes, are as follows:
With neither #1 or #2 used every server call returns a no access-control-allow-origin error (expected)
With both #1 and #2 used I receive an error that I am enabling CORS twice with the same value (expected)
If I only use #1 I don't receive a CORS error but every API method returns a 405 not allowed error
If I only use #2 every api call returns a no access-control-allow-origin error
Question: How can I globally enable CORS for my .NET Web Api project hosted in Azure?
appstart and register code:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
public static void Register(HttpConfiguration config)
{
// Enable CORS
// TODO, * below is debug only
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
I think this is the common issue with IIS default optionshandler. You have to update your Web.Config to disable defaults handlers. This is what I use for ASP.Net vnext hosted on Azure.
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="WebDav" />
<remove name="OPTIONSVerbHandler" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
I found that adding the Allow headers to web.config was the simplest way to get things working for me. Note you can't use both methods, you must choose one or the other.
I believe the solution to your 405 Not Allowed error is that you also need to include a line like this in web.config:
<add name="Access-Control-Allow-Headers" value="Authorization, Origin, Content-Type "/>
If you are still getting that error, you may need to include additional values from this list:
<add name="Access-Control-Allow-Headers" value="Access-Control-Allow-Headers, Authorization, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers" />
I am trying to remove unwanted Cache-Control, Pragma and Expires HTTP headers in responses from a Web Api 2 project hosted on an Azure website in Standard mode.
I have tried the following in Global.asax Application_PreSendRequestHeaders:
var headers = ((HttpApplication)sender).Context.Response.Headers;
headers.Remove("Cache-Control");
headers.Remove("Pragma");
headers.Remove("Expires");
This works when debugging in Visual Studio. But on Azure, the headers are only removed for GET requests and not HEAD or POST requests.
Grateful for any suggestions!
Azure Web Sites supports the request filtering module, so you can do this in your web.config:
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="Cache-Control" />
<remove name="Pragma" />
<remove name="Expires" />
</customHeaders>
</httpProtocol>
</system.webServer>
Disclaimer: I am not condoning the removal of these headers, which are an essential part of the HTTP protocol.
Removing cache headers says to clients "it is entirely up to you to decide how to cache this response", which may result in odd and hard-to-reproduce errors in production. If you want to disable caching, you should set these headers to values which explicitly disable caching:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="no-cache" />
<add name="Pragma" value="no-cache" />
<add name="Expires" value="-1" />
</customHeaders>
</httpProtocol>
</system.webServer>
I have created a custom webdav implementation with a HttpHandler, to serve files in a database via webdav protocol to a client.
On Cassini, my VS Development server I can access this without problems.
Now I am trying to debug this site in IIS, and that doesn't work.
I have the IIS 7.5 Webdav module uninstalled.
Some snippets of my web.config:
<system.web>
...
<httphandlers>
<add type="Test.WebDAVHandler, Test" verb="*" path="*"></add>
</httphandlers>
...
</system.web>
<system.webserver>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule">
</remove>
</modules>
<validation validateIntegratedModeConfiguration="true">
<defaultdocument enabled="true">
<files>
<add value="example.aspx"></add>
</files>
</defaultdocument>
<handlers accessPolicy="Read,Write,Execute,Script">
<remove name="WebDAV">
<add name=".NET Runtime" verb="*" path="*" preCondition="classicMode,runtimeVersionv2.0,bitness64" requireAccess="None" resourceType="Unspecified" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" modules="IsapiModule">
</add>
</handlers>
</validation>
</system.webserver>
When I connect to this site by using the Map network drive option of Windows 7 and inspect the requests using Fiddler, I see that the after some authentication, the client does the following request:
OPTIONS localhost/explorer and gets the following (shortened) response.
HTTP/1.1 200 OK
Allow: OPTIONS, TRACE, GET, HEAD, POST
I am missing some allowed verbs here, like PROPFIND.
The next request the client does is a PROPFIND.
The server responds with a 405 Method not allowed.
I looked at the request tracing, and the DefaultDocumentModule is causing this error.
When I disable this module, the DirectoryListingModule causes this 405.
Does anyone have a clue how to fix this, so that I can use webdav with my custom handler?