Related
I know this question has been asked plenty of times, each with similar answers, but after hours on this problem, I've yet to get it resolved, so I'm hoping additional suggestions may be provided.
I'm getting Error 405 - Method not allowed
I've removed the WebDAV entries from the module and handler section as suggested.
I've also changed the ExtensionlessUrlHandler-Integrated-4.0. Removed it first as suggested but didn't work so re-added it but with a slightly different definition <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*."
verb="GET,POST,OPTIONS,PUT,DELETE"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
where each verb is defined rather than using *
I've ensure CORS was enabled i.e. app.UseCors(CorsOptions.AllowAll); is called from my Startup class in public void Configuration(IAppBuilder app)
Access-Control-Allow-Methods has been set in my web.config
The weird thing is that it works just fine for DELETE but not for PUT.
Here's my System.WebServer section from my web.config:
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/>
</modules>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods"
value="GET,POST,OPTIONS,PUT,DELETE" />
</customHeaders>
</httpProtocol>
<handlers>
<clear/>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<remove name="WebDAV" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*."
verb="GET,POST,OPTIONS,PUT,DELETE"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
When I run Fiddler, I'm getting the following:
HTTP/1.1 405 Method Not Allowed
Allow: GET,POST
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/10.0
X-SourceFiles: =?UTF-8?B?RDpcU3BpbmRldlxXb3JrXEpvaWZmTGlzdGluZ05lnM=?=
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST,OPTIONS,PUT,DELETE
Date: Mon, 15 Jul 2019 23:41:32 GMT
Content-Length: 79
{
"message": "The requested resource does not support http method 'PUT'."
}
As you can see, the Access-Control-Allow-Origin and Access-Control-Allow-Methods appears to be set correctly but the Allow: is still set to GET,POST. Why is that? Where am I suppose to change this to have all the verbs?
And finally my action in my web controller is defined as follows:
[HttpPut]
[Route("id:{Guid}")]
public async Task<IHttpActionResult> UpdateCompany(Guid id)
{
}
Pretty standard stuff!
Any ideas and/or suggestions? Remember that I'm concentrating on getting this to work on IIS Express. Once I've got that resolved, I'll check it out in IIS but I really want to get to the bottom of this first.
Any help much appreciated.
Thanks.
UPDATE-1
I've just found an article from Microsoft regarding CORS, and even thought I'm enabling it as mentioned above, I've noticed that I don't have any references in my list of references to Microsoft.AspNet.WebApi.Cors which is odd and when I try to add the [EnableCors...] attribute, no references are shown which would indicate even more clearly that it may not be installed properly or at all.
I'll check that tomorrow and update.
I've also forgot to mention that OWIN is installed and set up. In the event this may give more clues as to why I still can't resolve this problem.
UPDATE-2
My add company (POST) is defined as follows:
[HttpPost]
public async Task<IHttpActionResult> AddCompany (
CompanyRequestDto companyRequestDto)
{
}
My update company (PUT) is defined as follows:
[HttpPut]
public async Task<IHttpActionResult> UpdateCompany (
Guid Id,
CompanyRequestDto companyRequestDto)
{
}
and my WebApiConfig.cs has the following route defined in it:
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
I've removed [Route("id:{Guid}")] as I thought it could have been that, but it's not. Same issue.
As Andrei Dragotoniu suggested, commenting out my UpdateCompany function generated the very same error which means another function is being hit but I have no idea which one as none of the breakpoints I've put are being hit, nor, any of them are defined as PUT so it's confusion. I'm sure we'll get to the bottom of it.
UPDATE-3
I feel really stupid right now!! After wasting so much time researching this problem, it actually wasn't there! Unlike a POST request where you only post the object, the PUT request expected a CompanyId as part of the query string which I had omitted and cause the problem!
http://localhost:12345/Companies
instead of
http://localhost:12345/Companies/61770BAA-78A6-E911-AEB1-001A7DDA7111
Anyway, I'm glad I'm up and running and I hope nobody else will do something as silly as this but if you do, hopefully, this will help!
Do not do this on IIS Express, that's pointless. Get it working in proper IIS instead.
One thing to check, the error method tells you that the particular method you're accessing does not support PUT. This doesn't mean that the PUT verb is not enabled in config. What it means is that the particular method you're accessing does not support it.
You need to check and see which endpoint is being hit because it doesn't seem to be the one you think. Check your rules basically. Remember they get applied in order so you really want your most concrete ones to be loaded first and the most general one at the end.
One quick way to check this is to comment out the UpdateCompany(Guid id) endpoint and see if you still get the same response when you repeat the call in Postman. If you do, then it's obvious that your request is being handled by a different endpoint, not the one you think.
When issuing a perfectly cromulent verb to a local IIS Express web-site under Visual Studio 2013:
CROMULENT http://localhost:7579/Handler.ashx HTTP/1.1
Host: localhost:7579
the server responds with the error:
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS, TRACE
That is a request to a "generic handler" (i.e. .ashx). If if i try again to a static resource:
SCHWIFTY http://localhost:7579/Default.htm HTTP/1.1
Host: localhost:7579
the server responds with the error:
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS, TRACE
This is all by way to trying to use HTTP verbs:
DELETE http://localhost:7579/Handler.ashx HTTP/1.1
Host: localhost:7579
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS, TRACE
PUThttp://localhost:7579/Handler.ashx HTTP/1.1
Host: localhost:7579
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS, TRACE
This question has been asked to death, sometimes by me. But nobody has ever come up with a solution.
</Question>
Microsoft's Bug
The problem, fundamentally, is that Microsoft ships IIS and IISExpress broken by default. Rather than handling HTTP verbs, as a web-server is required to do, they don't handle verbs.
This can most easily be seen when managing full IIS running on Windows Server. Pick any of the built-in handlers (e.g. the cshtml handler), and you can see that someone thought it would be hilarious if it only worked with GET, HEAD, POST, and DEBUG verbs:
rather than correctly implementing support for HTTP in an HTTP server.
The question becomes:
why exactly doesn't it work
how exactly to fix it
how to fix it in IIS Express (without any management tools)
why it continues to be shipped, year after year, broken
Question 1. Why doesn't it work?
The first question is why doesn't it work. Let's look at an IIS server where we've removed every handler except the basic Static file handler:
The handler is configured to all all verbs:
The only handler left is set to allow any verb. Yet if we issue a request to the web server we get the error:
DELETE http://scratch.avatopia.com/ HTTP/1.1
Host: scratch.avatopia.com
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS, TRACE
Server: Microsoft-IIS/7.5
Why is this happening?
Why didn't it work? Where is the configuration option that says:
GET
HEAD
OPTIONS
TRACE
because the server itself is saying those are the only supported verbs.
Yet if we change it to a GET it works fine:
GET http://scratch.avatopia.com/ HTTP/1.1
User-Agent: Fiddler
Host: scratch.avatopia.com
HTTP/1.1 200 OK
Content-Type: text/html
Question 2. How to fix it?
The common wisdom is to remove WebDAV. Nobody knows what WebDAV is, how it could be a problem, why it is a problem, or why it exists if it only causes problems. WebDAV can be removed as a handler from the IIS administration user interface:
which is identical to adding a remove entry from the handlers section in web.config (the UI itself adds the entry to web.config for you):
<system.webServer>
<handlers>
<remove name="WebDAV" />
</handlers>
</system.webServer>
Except this doesn't work. So how do we fix it?
Starting with IIS it seems that WebDAV has become even more of a virus. Rather than simply disabling it as a handler, you have to completely install or remove it as a module:
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
</handlers>
</system.webServer>
That sounds like a reason idea, except in my test case, on IIS 7.5, WebDAV is both not installed, and removed as a module:
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS, TRACE
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Tue, 10 May 2016 19:19:42 GMT
Content-Length: 0
So, if we can figure out how to solve the problem, we can answer question number two.
Question 3. How to fix it in IIS Express
Starting with Visual Studio 20131, Visual Studio no longer uses a mini web-server called Cassini. It uses a portable install of IIS Express itself (i.e. IIS Express Windows feature doesn't need to be installed).
Most of the above fix (attempts) (fail) in IIS. But nobody has dealt with them in IIS Express of Visual Studio 2013 (which is how this question is different from any others).
Question 4. Why does this keep happening?
It's been over 15 years, and this still keeps happening. There must be a good reason why IIS does not function as a web-server. But what is it? I've not been able to find any knowledge base article, or blog post, explaining why the IIS team refuses to function correctly.
Bonus Reading
The most popular Stackoverflow question for this problem: ASP.NET Web API - PUT & DELETE Verbs Not Allowed - IIS 8
Research Effort
HTTP Error 405.0 - Method Not Allowed, with POST (no answer, php)
HTTP Error 405.0 - Method Not Allowed (no answer)
POST verb not allowed (php)
HTTP Error 405.0 - Method Not Allowed in ASP.net MVC5 (no answer, mvc)
JQuery File Uploader = error 405 IIS8.5 (jquery no answer)
IIS 7.5 405 Method Not Allowed for PUT from StaticFileModule (no answer, static module, iis)
The HTTP verb POST used to access path is not allowed ("don't use verbs")
http error 405 method not allowed error with web.API (uninstall WebDAV; already isn't)
Handling Perl IIS 7.5 (perl)
HTTP Error 405.0 - Method Not Allowed using Jquery ajax get (ajax)
What causes an HTTP 405 "invalid method (HTTP verb)" error when POSTing a form to PHP on IIS? (iis6, ftp, php)
http://forums.asp.net/t/1648594.aspx ("have you tried pinging your computer")
Angular $resource POST/PUT to WebAPI 405 Method Not Allowed (try removing WebDAV handlder and WebDAV module)
Http Error 405.0 - method not allowed iis 7.5 module staticfilemodule (no solution)
Unable to set up WebDAV with IIS 7 *(trying to setup webdav)*
Android SOAP request is returning HTTP Response 405 (no solution)
wcf service doesn't allow POST (wcf)
WebAPI Delete not working - 405 Method Not Allowed (WebAPI; remove WebDAV)
I seem to pick up on a bit of frustration in the question, so the actual question is a bit unclear. What specifically is it that you are trying, but failing, to do? What do you expect of the answer?
Anyway, based on this comment in the question:
This is all by way to trying to use HTTP verbs:
and the corresponding samples involving a generic handler, I'll take a stab at showing what is needed to make it possible to PUT and DELETE a generic handler.
In order to allow PUT and DELETE on a generic handler, you must allow it in the web.config of the application. To do that you should register a handler for *.ashx as follows:
<system.webServer>
<handlers>
<add name="SimpleHandlerFactory-Integrated-WithPutDelete"
path="*.ashx"
verb="GET,HEAD,POST,DEBUG,PUT,DELETE"
type="System.Web.UI.SimpleHandlerFactory"
resourceType="Unspecified"
requireAccess="Script"
preCondition="integratedMode" />
</handlers>
</system.webServer>
Depending on how you originally set up the web site/application, there may or may not be a handler registered for type="System.Web.UI.SimpleHandlerFactory" in your web.config file. If there is one, you should be able to just modify that entry and add the verbs you want to allow.
You'll note that this entry has the preCondition="integratedMode". This should, I believe, work when debugging in Visual Studio using IIS Express. In a real IIS deployment, the handler registration may need to be modified to match the application pool that will run the application. For an application running in classic mode (not integrated), it would look something like this (not tested so may be wrong):
<system.webServer>
<handlers>
<add name="SimpleHandlerFactory-ISAPI-4.0_64bit-WithPutDelete"
path="*.ashx"
verb="GET,HEAD,POST,DEBUG,PUT,DELETE"
modules="IsapiModule"
scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
preCondition="classicMode,runtimeVersionv4.0,bitness64"
responseBufferLimit="0" />
</handlers>
</system.webServer>
The exact details would depend on the framework version an bit-ness of the application pool.
If you are debugging in Visual Studio using IIS Express, you should have a look at the applicationhost.config which sets up a lot of the defaults regarding IIS Express. It is located in:
My Documents\IISExpress\config
The untested handler registration above for a classic pipeline application pool is a slight modification of a handler registration in that file. There are in my environment 6 separate entries for *.ashx, with varying preconditions, in that file.
It might be a good idea to explicitly remove all of these in your web.config if you want to have your own registration which allows PUT and DELETE. Not all of them would actually be active/registered at the same time since the preconditions are (I suppose) mutually exclusive, but at least for me it works to just remove them all, one after the other. In my environment the section with the removes looks like this:
<remove name="SimpleHandlerFactory-ISAPI-4.0_64bit"/>
<remove name="SimpleHandlerFactory-ISAPI-4.0_32bit"/>
<remove name="SimpleHandlerFactory-Integrated-4.0"/>
<remove name="SimpleHandlerFactory-Integrated"/>
<remove name="SimpleHandlerFactory-ISAPI-2.0"/>
<remove name="SimpleHandlerFactory-ISAPI-2.0-64"/>
Hope this shines at least a bit of light into dark places!
okay so i ran into this same exact problem on IIS 7.5 when trying to PUT or DELETE it returned a 405.
i was specifically trying to setup a MEAN stack with IISnode module. when accessing the static HTML file IIS was serving up i was able to GET and PUSH but not PUT or DELETE.
-- the problem --
i believe that the issue is with IIS server itself. take a look at this post here:
https://blogs.msdn.microsoft.com/saurabh_singh/2010/12/10/anonymous-put-in-webdav-on-iis-7-deprecated/
https://support.microsoft.com/en-us/kb/2021641
it appears that IIS no longer allows Anonymous PUT or DELETE
so in the end i just went with a nodejs webserver instead
-- however --
i have not tried this but perhaps you might want to look into modifying the IIS system config file itself called the ApplicationHost.config located here:
C:\Windows\System32\inetsrv\config
make sure to use notepad with administrator privileges
let me know how it goes and i might try and do this later when i have time
There is a lot of talk about removing WebDAV and that will fix the problem - but if you're wondering what WebDAV is and what its used for, check out this page:
https://www.cloudwards.net/what-is-webdav/
Holy Damn, many research these 2 days....
No WebDav installed, no typical handler modifications (SimpleHandlerFactory, ExtensionlessUrl)
For those using any PHP Frameworks just as: Laravel, CakePHP etc
I couldn't make IIS Failed Tracing Logs work, so...
All I did was, modify PHP handler [MODIFY: php-X_VERSION]:
<handlers>
<remove name="php-X_VERSION" />
<add name="php-X_VERSION" path="*.php" verb="GET,HEAD,POST,PUT,DELETE" modules="FastCgiModule" scriptProcessor="D:\Program Files\PHP\X_VERSION\php-cgi.exe" resourceType="Either" requireAccess="Script" />
</handlers>
I have no WebDAV installed, and am running IIS Express from VS2019. After some digging, I came upon the applicationhost.config file used by IIS Express, and ended up with a solution by changing my own project web.config file. In the system.webServer/handlers section, add the following:
<system.webServer>
<handlers>
<remove name="PageHandlerFactory-ISAPI-4.0_64bit"/>
<remove name="PageHandlerFactory-ISAPI-4.0_32bit"/>
<remove name="PageHandlerFactory-Integrated-4.0"/>
<remove name="PageHandlerFactory-Integrated"/>
<remove name="PageHandlerFactory-ISAPI-2.0"/>
<remove name="PageHandlerFactory-ISAPI-2.0-64"/>
<add name="PageHandlerFactory-ISAPI-4.0_64bit" path="*.aspx" verb="GET,HEAD,POST,DEBUG,PUT" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="PageHandlerFactory-ISAPI-4.0_32bit" path="*.aspx" verb="GET,HEAD,POST,DEBUG,PUT" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="PageHandlerFactory-Integrated-4.0" path="*.aspx" verb="GET,HEAD,POST,DEBUG,PUT" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="PageHandlerFactory-Integrated" path="*.aspx" verb="GET,HEAD,POST,DEBUG,PUT" type="System.Web.UI.PageHandlerFactory" preCondition="integratedMode,runtimeVersionv2.0" />
<add name="PageHandlerFactory-ISAPI-2.0" path="*.aspx" verb="GET,HEAD,POST,DEBUG,PUT" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="0" />
<add name="PageHandlerFactory-ISAPI-2.0-64" path="*.aspx" verb="GET,HEAD,POST,DEBUG,PUT" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" responseBufferLimit="0" />
</handlers>
</system.webServer>
All this does, is it adds the word "PUT" to the verb attribute of each handler.
I also have to add that I am working on an older project and created the API endpoints with *.aspx files, which is why other solutions found googling did not work. So if you are using VS2019 and get the error 405.0 - Method not Allowed and you already removed WebDAV and expose your API with .aspx files this might work.
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...!!!
Following the procedure in this article I disabled the ARR Affinity cookie on my Azure Web App with this header in my responses:
Arr-Disable-Session-Affinity: True
It does remove the cookie, which is very much a good thing. But, the header itself is still coming through. This header doesn't really hurt anything, but according to that same doc it shouldn't be there:
If you add the Arr-Disable-Session-Affinity header to disable the affinity cookie, ARR will not set the cookie, but it will also remove the Arr-Disable-Session-Affinity header itself, so if your process is working correctly, you will see neither.
So...how do I get it to remove the header, too?
if you have added the Arr-Disable-Session-Affinity custom header as below in your Azure Web App web.config, then it is a correct behavior you still see the Arr-Disable-Session-Affinity header with value set to true and the ARR cookie removed in your HTTP response. I think it's an incorrect statement in the reference blog you provided which stated that the Arr-Disable-Session-Affinity header will be removed.
If you want to remove that header then the cookie will present, it's mutually exclusive.
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Arr-Disable-Session-Affinity" value="true" />
</customHeaders>
</httpProtocol>
The article you refer to doesn't say specifically how to add the header so I can't tell if you did it correctly. I haven't tested but according to this article you should set it in the Application_PreSendRequestHeaders:
protected void Application_PreSendRequestHeaders()
{
Response.Headers.Remove("Server");
Response.Headers.Remove("X-AspNet-Version");
Response.Headers.Remove("X-AspNetMvc-Version");
Response.Headers.Add("Arr-Disable-Session-Affinity", "True");
}
Our site is not currently safe from clickjacking, so I went into the web.config and added
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="DENY" />
</customHeaders>
</httpProtocol>
</system.webServer>
This is very straight forward code. My issue is that it's just not working. The questions I have are:
Is there a way for me to see if the X-Frame-Options is in the header response? I looked for it with httpfox and got nothing, so I can't verify if the web.config is actually putting things in the header.
Why is this not working? What can I do to test or move forward?
I did try to add it in the Global.asax in the Application_Start method, but I cant seem to "hit" this method when I debug; it does not hit breakpoints.
private void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
HttpContext.Current.Response.AddHeader("x-frame-options", "DENY");
LogHelper.Info("Cost of Care Web Application Starting");
}
I would like to add that I have tried to add it straight into the head tag and I've also tried to add it in a meta tag like so
<meta http-equiv="X-Frame-Options" content="deny">
The X-Frame-Options header can be used to control whether a page can be placed in an IFRAME. Because the Framesniffing technique relies on being able to place the victim site in an IFRAME, a web application can protect itself by sending an appropriate X-Frame-Options header.
To configure IIS to add an X-Frame-Options header to all responses for a given site, follow these steps:
Open Internet Information Services (IIS) Manager.
In the Connections pane on the left side, expand the Sites folder and select the site that you want to protect.
Double-click the HTTP Response Headers icon in the feature list in the middle.
In the Actions pane on the right side, click Add.
In the dialog box that appears, type X-Frame-Options in the Name field and type SAMEORIGIN or DENY in the Value field.
Click OK to save your changes.
Since my comments answered the question here's the end result:
For some reason setting the X-Frame-Options in web.config doesn't seem to actually work even though the documentation makes it sound like it should.
An easy work around is to set the headers manually using:
Response.AddHeader("X-Frame-Options", "DENY");
If you need this set for every request with no exceptions you can add the Application_BeginRequest to Global.asax:
protected void Application_BeginRequest()
{
Response.AddHeader("X-Frame-Options", "DENY");
}
The answer of siva.k does not work in connection with MVC5 as the header is generated twice here. The following code should work:
protected void Application_Start()
{
// MVC5 generates the "X-Frame-Options SAMEORIGIN" header by default, the following line disables the default behaviour
System.Web.Helpers.AntiForgeryConfig.SuppressXFrameOptionsHeader = true;
}
protected void Application_BeginRequest()
{
Response.AddHeader("X-Frame-Options", "DENY");
}
The SuppressXFrameOptionsHeader flag was mentioned here: https://stackoverflow.com/a/20262211/3936440
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="default-src: https:; frame-ancestors 'self' X-Frame-Options: SAMEORIGIN" />
</customHeaders>
</httpProtocol>
</system.webServer>
Your web.config entry needs to be under content security policy to make use of current coding not previously depreciated. The value under content security policy of value="default-src: https: is unique to your website.
The content that matters is what comes after 'value="default-src: https:' but most importantly is contained within Content Security Policy.
Here is another thing to consider:
If you have a separate back-end and UI projects (as is very common for REST based sites), make sure that you put X-Frame-Options in the UI web.config. Your API is probably allowing cross site calls so adding the header to your API project would make no sense.
I found that some file types (.asp and .htm files) were getting the X-Frame-Options header added by this mechanism and others (.js) weren't. Using the IIS Admin utility I removed the header from the application level and added it at the server level, and then all files were getting the header added.