I have been following the Mozilla article on how to set up my website to allow Cross-site scripting requests. Using IIS Manager I have added the following HTTP Response Headers
Access-Control-Allow-Origin : *
Access-Control-Allow-Headers : Origin, SecurityPrivateKeyID
Access-Control-Allow-Methods : GET, POST, PUT, DELETE, OPTIONS
Despite this I keep getting a 405 Method Not Allowed
when my browsers (Firefox and Chrome) send the pre-flight request with a custom SecurityPrivateKeyID
header.
Request
OPTIONS /Service/Json/User.svc/ HTTP/1.1
Host: serviceprovider.com
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://client.com
Access-Control-Request-Method: GET
Access-Control-Request-Headers: securityprivatekeyid
Connection: keep-alive
Response
HTTP/1.1 405 Method Not Allowed
Allow: GET
Content-Length: 1565
Content-Type: text/html; charset=UTF-8
Server: Microsoft-IIS/8.0
access-control-allow-origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Origin, SecurityPrivateKeyID
Date: Sat, 23 Mar 2013 08:35:03 GMT
The service works fine when accessing directly at http://serviceprovider.com/Service/Json/User.svc/
.
Any ideas on what I am doing wrong?
[note I have changed my hosts files to point client.com and serviceprovider.com at my machine]
[a solution using JSONP will not do as my web service must be able to consume POST, PUT and DELETE methos]
My IIS 8 instance is fresh installation, it seems I needed to make some modifications to the Handler Mappings
In the event that any of the sugggested changes break your existing websites it's best to make a backup of the applicationhost.config file
C:\Windows\System32\inetsrv\config
applicationhost.config
As a starting point I removed all unused Handler Mappings to reduce the problem space. You can do this by modifying the applicationhost.config
directly or by using IIS Manager
My websites are heavily service based and just depend on static files and files with the .aspx
and .svc
files extensions. I also manually removed all references to .NET 2.0
throughout the configuration file.
This seems to be the fix.
Add Module Mapping
Add Module Mapping
dialog use the following values.
Request path
- *
Module
- ProtocolSupportModule
Executable
- [Leave blank]Name
- [Whatever you want]Request Restrictions
Mapping
tab, unckeck Invoke handler only if request is mapped to
Verbs
tab ensure OPTIONS
is selectedAccess
tab select Script
My resulting Handlers configuration looks like this
<handlers accessPolicy="Read, Script">
<add name="OPTIONS" path="*" verb="OPTIONS" modules="ProtocolSupportModule" resourceType="Unspecified" />
<add name="svc-Integrated-4.0" path="*.svc" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="SecurityCertificate" path="*.cer" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="File" />
<add name="ISAPI-dll" path="*.dll" verb="*" modules="IsapiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" />
<add name="PageHandlerFactory-Integrated-4.0" path="*.aspx" verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="CGI-exe" path="*.exe" verb="*" modules="CgiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0" />
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
</handlers>