IIS CORS configuration for one file - iis

Microsoft claims CORS can be enabled using the CORS module of IIS on a single file (point #1 see reference).
https://learn.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference
How can this be done? I don't see anything restricting the rules by site or file.
Does anyone know where the DTD for this module is? I can figure it out if I have the specification.

Thanks Lex li!
An example of how to do this is below:
<location path="myFile.json">
<system.webServer>
<cors enabled="true">
<add origin="https://*.myDomain.com">
<allowHeaders allowAllRequestedHeaders="true">
</allowHeaders>
</add>
</cors>
</system.webServer>
</location>
Obviously you can add other CORS attributes in the middle as you see fit, but this solves the "location" part of my issue.

Just would like provide a GUI way to set cors,
You could go to IIS manager ->site node->content view->select the file you want to set CORS->switch back to feature view.
Now you will see the file in your site node.You can go to configuration manager and set CORS module via web.config.

Related

Remove duplicate files from IIS for same application

I have X the same applications in IIS(some code/exe, but different config file).
Would it be possible to put duplicate files to some folder?
For example I have applications:
Canada.weather.com
usa.weather.com
mexico.weather.com
Uses same .dll and .exe, but have different config.
As Lex says, we don't suggest you to put duplicate files to some folder. If one of the dll is missed or not, it will make all the sites down.
If you still want to do this , you could apply the setting in applicationHost.config and wrapping it in a tag.
The applicationhost.config file path :
%windir%\system32\inetsrv\config\applicationHost.config
Each sites will have its own location, you could add the custome configuration inside each location tag.
Like belowl, I enable the windows auth for "BrandoTestSite":
<location path="BrandoTestSite">
<system.webServer>
<security>
<authentication>
<windowsAuthentication enabled="true" />
<anonymousAuthentication enabled="false" />
</authentication>
</security>
</system.webServer>
</location>
Notice: This way is lower maintainability. We don't suggest you choose this way to manage mutiple application.

Applying different Content Security Policies to different directories with NWebSec

I've got an ASP.NET MVC website with a heavily customised Umbraco 6 backend as the site's CMS.
I've been upgrading the content security policy (CSP) headers all across the site, which I am doing by use of NWebsec, and the website now happily uses CSP 3 strict-dynamic and there are nonces on every script tag, and everything works fine.
Unfortunately, I haven't been able to apply the same changes to the Umbraco admin area, so most of that does not work at all.
So what I want to do is apply the strict CSP 3 policy to the public-accessible parts of the website, and apply a relaxed CSP policy to the locked-down admin area.
The Umbraco admin area sits under a subdirectory /umbraco/ so I thought the best way to implement this would be to use two different location elements in the site's Web.config file.
So my Web.config now looks something like:
<!-- Specific CSP for Umbraco -->
<location path="~/umbraco">
<nwebsec>
...
<content-Security-Policy enabled="true">
...
<script-src self="true" unsafeInline="true" unsafeEval="true">
<add source="data:" />
</script-src>
...
</content-Security-Policy>
</nwebsec>
</location>
<!-- default CSP for everything else -->
<location path=".">
<nwebsec>
...
<content-Security-Policy enabled="true">
...
<script-src self="true" unsafeInline="true" unsafeEval="false" strictDynamic="true">
</script-src>
...
</content-Security-Policy>
</nwebsec>
</location>
But this applies the default config to the whole site.
I'm not sure whether I've got the config wrong, or maybe NWebSec doesn't support what I'm trying to do, or there's some specific issue with redirects or something else.
Fixed by creating a separate Web.config in the /umbraco subdirectory.
Main Web.config:
<location path="." allowOverride="true">
<nwebsec>
...
<content-Security-Policy enabled="true">
...
<script-src self="false" unsafeInline="true" unsafeEval="false" strictDynamic="true">
<add source="www.example.com" />
</script-src>
...
</content-Security-Policy>
</nwebsec>
</location>
Web.config in the /umbraco subdirectory:
<location path="." allowOverride="true">
<nwebsec>
...
<content-Security-Policy enabled="true">
...
<script-src self="true" unsafeInline="true" unsafeEval="true" strictDynamic="false">
<clear/>
<add source="www.other-example.com" />
</script-src>
...
</content-Security-Policy>
</nwebsec>
</location>
The config in the subdirectory overrides the main Web.config - so strictDynamic="false" switches off use of those CSP3 nonces, and the clear element removes all pre-existing elements in the collection so a new set of domains can be used.

CORS problems in WebAPI hosted in IIS

I'm trying to implement an application that uses the same Token Based Authentication mechanism demonstrated in this really awesome example by Taiseer Joudeh.
In my application I kept encountering Cors problems. In some configurations I would get a 500 error on the Preflight (OPTIONS) request for the POST to get the token or I could get the token but then get a 404 error on the preflight request for the GET request to the actual API call with the Bearer token.
One difference was that Taiseer's code was setup to host in IISExpress (or Azure) and mine is hosted on Local IIS (running on Windows 7 at the moment).
On a hunch I tried hosting his API under Local IIS and I found the exact same problem. (500 error on the preflight request for the token and it looks like the actual API will work properly)
From what I've been reading it seems like this may be some conflict between the modules and handlers in IIS and the Cors implementation in WebApi but Taiseer's implementation works when hosted in Azure so perhaps it is a difference in the version of IIS (I'm currently running under Windows 7).
How can I sort out what is causing the problem?
The root of the problem
The Token action is not hosted in a controller but is instead built in somewhere in the lower level plumbing. The only access to the mechanism is through the override method GrantResourceOwnerCredentials() in the class that extends OAuthAuthorizationServerProvider. (In our case is ApplicationOAuthProvider.cs).
GrantResourceOwnerCredentials() does have the context available but it is not called as part of the PreFlight request so you have no way to insert the appropriate PreFlight response headers for CORS.
The solution
We eventually settled on the following solution. I'm not a big fan of it because it forces these headers into every response but at least it works.
The solution was to override Application_PreSendRequestHeaders() method in Global.asax to insert the appropriate headers.
Global.asax.cs
void Application_PreSendRequestHeaders(Object sender, EventArgs e)
{
var origin = Request.Headers.Get("Origin");
var validOrigins = ConfigurationManager.AppSettings["allowedCorsOrigins"].Split(',');
if(validOrigins.Any(o => o == origin))
{
Response.Headers.Set("Access-Control-Allow-Origin", origin);
Response.Headers.Set("Access-Control-Allow-Credentials", "true");
Response.Headers.Set("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization, withcredentials, Prefer");
Response.Headers.Set("Access-Control-Expose-Headers", "Claims, *");
Response.Headers.Set("Access-Control-Max-Age", "600");
Response.Headers.Set("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS");
}
}
This requires the following web.config entries:
web.config
<configuration>
<appSettings>
<add key="allowedCorsOrigins" value="http://www.allowedsite1.net,http://localhost:22687" />
<add key="allowedCorsMethods" value="get, post, put, delete, options, batch" />
<add key="allowedCorsHeaders" value="*" />
</appSettings>
...
</configuration>
The reason for the loop to search for the valid origins is that you can't respond with a list of allowed origins...
This solved most of the problems with one exception (If I recall correctly was problems with PUT and DELETE verbs). This required removing the "ExtensionlessUrlHandler-Integrated-4.0" and re-adding it with a path and verb in the handlers section of the web.config.
web.config (2nd change)
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="" />
</handlers>
....
</system.webServer>
Useful links related CORS
Really good description of PreFlight for CORS
Excellent Sample Application using Token Auth
It is not the IdentityServer you are using but it could be the same problem. Regarding to the IdentityServer´s Github page you have to activate RAMMFAR (runAllManagedModulesForAllRequests) for your application when running under the IIS.
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
</modules>
</system.webServer>
I had this same issue, I did everythin as suggested by Mr. Tom hall. But still chrome reported no Access-control-allow-origin header is present.. after inspecting with fidler i realized that my request goes through a proxy server and my proxy server is handling the preflight options request..
So in "internet options" i removed the proxy server and found out that everything is working...!!!

web.config causes HTTP 500 issue with virtual directory in IIS

I'm fairly new to IIS so apologies if this is a basic question.
I have an IIS config serving an internal company website (php instead of asp.net). The prod version of the website is at the 'Default Web Site' level and I've got demo and test versions of the website mapped as virtual directories. The demo and test version are essentially copies of the prod directory. I've noticed the with the web.config copied to these VDs, I get an error 500 on the root url for the VD only. I.E. main website is https://mainwebsite.com and works fine but https://mainwebsite.com/demo/ doesn't work while https://mainwebsite.com/demo/index.php works fine.
The web.config file is pretty basic:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
</handlers>
<defaultDocument>
<files>
<add value="index.php" />
</files>
</defaultDocument>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="00:03:00" />
</staticContent>
</system.webServer>
</configuration>
Moving the web.config file out of the way in the VD resolves the issue. Even though the files are identical, I wouldn't think that the file should cause a conflict as my understanding is that IIS supports multiple web config files.
Although I have a workaround in place by renaming or deleting the file, I am wondering if there's a way to keep the file in place without it causing this error.
Thanks to Panama Jack in the comments, I was able to resolve my issue.
I got this response with detailed errors:
Error Summary
HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.
And further down:
Config Error
Cannot add duplicate collection entry of type 'add' with unique key attribute 'value' set to 'index.php'
To resolve, I simply commented out this line in the web.config XML:
<add value="index.php" />
I'm sure there's a better way to approach this but for now, this gets me my answer and also how to get more info from IIS when the logs are not useful.
if you create a virtual directory to another web root
web.config will cause this (personally I think the location of this file is totally insane.. mixed with htm and images etc. )
Replicate the directory somewhere else without the web.config file/excluding it..then point the virtual directory there.. & have a task set up to copy newer files over..

"405 method not allowed" in IIS7.5 for "PUT" method

I use WebClient type to upload *.cab files to my server. On the server side, I registered a HTTP handler for *.cab file with the PUT method as below:
<add name="ResultHandler" path="*.cab" verb="PUT" type="FileUploadApplication.ResultHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode" />
But I always get a "405 method not allowed" error. The response said the allowed methods are as below:
Headers = {Allow: GET, HEAD, OPTIONS, TRACE
Content-Length: 1293
Content-Type: text/html
Date: Fri, 27 May 2011 02:08:18 GMT
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET}
Even if I explicitly allow the PUT method in the IIS Request Filtering for my web application, the same error still occurs.
I suspect this is a IIS related issue. I'm hoping someone could shed some light on this for me.
Often this error is caused by the WebDAV module that try to handle this kind of requests. An easy solution is to remove it from modules and from handlers of the system.webServer section just inside your web.config file.
Here a configuration example:
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
</handlers>
</system.webServer>
I enabled the Failed Request Tracing, and got the following info:
<EventData>
<Data Name="ContextId">{00000000-0000-0000-0F00-0080000000FA}</Data>
<Data Name="ModuleName">WebDAVModule</Data>
<Data Name="Notification">16</Data>
<Data Name="HttpStatus">405</Data>
<Data Name="HttpReason">Method Not Allowed</Data>
<Data Name="HttpSubStatus">0</Data>
<Data Name="ErrorCode">0</Data>
<Data Name="ConfigExceptionInfo"></Data>
</EventData>
So, I uninstalled the WebDAVModule from my IIS, everything is fine now~
The IIS tracing feature is very helpful.
I tried most of the answers and unfortunately, none of them worked in completion.
Here is what worked for me. There are 3 things to do to the site you want PUT for (select the site) :
Open WebDav Authoring Rules and then select Disable WebDAV option present on the right bar.
Select Modules, find the WebDAV Module and remove it.
Select HandlerMapping, find the WebDAVHandler and remove it.
Restart IIS.
Taken from here and it worked for me:
Go to IIS Manager.
Click on your app.
Go to "Handler Mappings".
In the feature list, double click on "WebDAV".
Click on "Request Restrictions".
In the tab "Verbs" select "All verbs" .
Press OK.
I had this problem with WebDAV when hosting a MVC4 WebApi Project. I got around it by adding this line to the web.config:
<handlers>
<remove name="WebDAV" />
<add name="WebDAV" path="*" verb="*" modules="WebDAVModule"
resourceType="Unspecified" requireAccess="None" />
</handlers>
As explained here: http://evolutionarydeveloper.blogspot.co.uk/2012/07/method-not-allowed-405-on-iis7-website.html
Best to just remove the unused WebDAV feature. Go to Programs and Features => Turn Windows Features On or Off and disable WebDAV Publishing under
Internet Information Services => World Wide Web Services => Common HTTP Features
Removing the WebDAV-module should be sufficient. Just change your Web.config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
Here is what worked for me:
Open up IIS and click on your Site.
Double Click on the Modules
Right Click on WebDavPublishing and remove.
Restart running WebSite.
I was using Angular 8 and was .NET core API.
I add the following in my service web.config file. That resolve my error.
<system.webServer>
<modules runAllManagedModulesForAllRequests="false">
<remove name="WebDAVModule" />
</modules>
</system.webServer>
I had the same problem, with a RESTful API running on aspnet core.
I didn't want to uninstall the WebDAV, and I tried most of the remedies described above. I tried to set the verbs="*" both on the site and on the server itself, but without success.
What did the trick for me was the following:
IIS Manager -> Sites -> MySite -> HandlerMappings -> aspNetCore -> Edit
-> Request Restrictions -> Access -> None (it was Script).
After that everything worked, even if I replaced the original WebDAV options.
Another important module that needs reconfiguring before PUT and DELETE will work is the options verb
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="OPTIONSVerbHandler" />
<remove name="WebDAV" />
<add name="OPTIONSVerbHandler" path="*" verb="*" modules="ProtocolSupportModule" resourceType="Unspecified" requireAccess="Script" />
</handlers>
Also see this post: https://stackoverflow.com/a/22018750/9376681
For whatever reason, marking WebDAVModule as "remove" in my web.config wasn't enough to fix the problem in my case.
I've found another approach that did solve the problem. If you're in the same boat, try this:
In the IIS Manager, select the application that needs to support PUT.
In the Features View, find WebDAV Authoring Rules. Double-click it, or select Open Feature from the context menu (right-click).
In the Actions pane, find and click on WebDAV Settings....
In the WebDAV Settings, find Request Filtering Behavior, and under that, find Allow Verb Filtering. Set Allow Verb Filtering to False.
In the Actions pane, click Apply.
This prevents WebDAV from rejecting verbs that it doesn't support, thus allowing a PUT to flow through to your RESTful handler unmolested.
Another tip from me. I have used PHP + IIS, and the Handler Mappings for PHP did not have the PUT verb.
Go to IIS Manager->Your site->Handler Mappings->PHPxx_via_FastCGI->Request Restrictions->Verbs, then add PUT.
That's it!
I had the same issues with PUT, PATCH and DELETE but didn't have anything with WebDav installed. Resolution 1 in this article finally helped me: http://support.microsoft.com/kb/942051
for asp.net core 5
IIS-> Sites -> MySite -> HandlerMappings -> aspNetCore -> Request Restrictions -> Access -> None (it was Script).
For me this error wouldn't go away and allow PUT methods, whatever i did.. uninstalled webdav, put configuration in web.config to remove webdav from handlers and modules, and set up PUT as an allowed verb on the request filters on iis.. and ensure iis handler mappings handling the request had PUT configured..
My problem was eventually due to bad installation of ASP.NET 4.5 Extensions. Removed everything related to asp.net from server roles and features. restarted. readded the roles and restarted. everything worked with above config.
--- The below will make PUT be accepted, but will send it to the wrong handler. --ignore the below
finally, adding PUT verb as allowed verb on TRACE handler mapping on iis worked.. since i had enabled failed error tracing, and this verb was not allowing the verb.
last time i had the same problem on another server's IIS, it was due to a missing '/' at the end of the URL since it was using a default handler without using the default document probably and now i realize that.. so check IIS handler mappings if nothing else helps.
I had this problem but nothing related to WebDAV was the issue. In my case, the client was sending a POST to www.myServer.com/api/chart. This call should be handled by the "ExtensionlessUrlHanlder-Integrated-4.0", however, somehow a local file structure was created in my server directory "...\Server\api\chart\". This meant that the "StaticFile" handler was being called instead. Deleting those local files finally solved the problem.
For Windows server 2012 -> Go to Server manager -> Remove Roles and Features -> Server Roles -> Web Server (IIS) -> Web Server -> Common HTTP Features -> Uncheck WebDAV Publishing and remove it -> Restart server.
I have a same problem for PUT and DELETE request in IIS10 for asp.net core 5.
I just added below lines in web.config and problem is resolve.
<system.webServer>
<modules runAllManagedModulesForAllRequests="false">
<remove name="WebDAVModule" />
</modules>
</system.webServer>
You can do solve by other way from IIS also.
In IIS, select the application
Add rules to allow HTTP verbs in Request Filtering (But this alone doesn't work).
Go to "Modules", then select the "WebDAV Publishing" module and remove it.
Go to "Handler Mappings", then select the "WebDAV" and remove it.
in cmd run IISRESET
This is my solution, alhamdulillah it worked.
Open Notepad as Administrator.
Open this file %windir%\system32\inetsrv\config\applicationhost.config
Press Ctrl-F to find word "handlers accessPolicy"
Add word "DELETE" after word "GET,HEAD,POST".
The sentence will become <add name="PHP_via_FastCGI" path="*.php" verb="GET,HEAD,POST,DELETE"
The word "PHP_via_FastCGI" can have alternate word such as "PHP_via_FastCGI1" or "PHP_via_FastCGI2".
Save file.
Reference: https://learn.microsoft.com/en-US/troubleshoot/iis/http-error-405-website
If you are only developing on your machine, using IIS to run your application and you are not going to use WebDAV then just go to Control Panel > Add or Remove Windows features and disable WebDAV
If IIS app pool is running under classic mode, make sure you have the following in your web.config
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE" modules="IsapiModule" scriptProcessor="c:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
In my case I had relocated Web Deploy to another port, which was also the IIS port (not 80). I didn't realize at first, but even though there were no errors running both under the same port, seems Web Deploy was most likely responding first instead of IIS for some reason, causing this error. I just moved my IIS binding to another port and all is well. ;)
To prevent WebDav from getting enabled at all, remove the following entry from the ApplicationHost.config:
<add name="WebDAVModule" />
The entry is located in the modules section.
Exact location of the config:
C:\Windows\System32\inetsrv\config\applicationHost.config
In case anyone still using ASP classic needs to solve the method not allowed trouble for ASP, you also need to re-register the ASP classic handler for telling it to handle additional verbs. By default, it only handles GET, HEAD and POST.
<system.webServer>
<!-- other stuff ... -->
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
<remove name="ASPClassic" />
<add name="ASPClassic" path="*.asp" verb="GET,HEAD,POST,PUT,DELETE,PATCH" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="File" />
</handlers>
</system.webServer>
In order to remove WebDAV module and handler using appcmd you can use this:
appcmd uninstall module WebDAVModule
appcmd clear config -section:system.webServer/handlers -"[name='WebDAV']"
This can also be use in a release pipeline if needed.

Resources