1

I work on a third party web based application, lets call it Po, by injecting company required modifications via JQuery which calls PHP code in a digital workplace type domain of ours https://digitalworkplace.staging.c.com

The digital workplace code then calls our API, using CURL and POST, which is on a different domain of ours, http://p.staging.c.com

This was previously all working fine until Po added in CSFR support on each of their application pages.

I get the CSRF token from the Po page where it is hidden in a field with id="csrf-nonce", name="CSRF_NONCE"

I make the AJAX call with the following settings:

$.ajaxSetup({
       headers: {
            'Content-Type': 'application/json; charset=UTF-8',
            'CSRF_NONCE' : csrf
       }
    });

$.ajaxPrefilter(function(options){
        options.beforeSend = function(xhr){
            xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
            xhr.setRequestHeader('CSRF_NONCE', csrf);
        }
    });

$.ajax({
        type: "POST",
        accept: 'application/json',
        crossOrigin: true,
        crossDomain: true,
        method: m,
        beforeSend: function(xhr){
            xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
            xhr.setRequestHeader('CSRF_NONCE', csrf);
        },
        url: u,
        data: d,
        dataType: "json",
        contentType: "application/json",
        swotId: s,
        async: a,
        headers: {
            "Content-Type": "application/json; charset=UTF-8",
            "CSRF_NONCE": csrf,
        },
        xhrFields: {
            withCredentials: true
        },
        success: function(xhr) {
            console.log("yippee");
        },
        error: function(e) {
            console.log(e);
        }
    });

If I run in Chrome and look at the Network info I see the General Header:

Request URL:https://digitalworkplace.staging.c.com/web/p/versio/mysql/getmasterordernumber
Request Method:OPTIONS
Status Code:200 OK
Remote Address:192.168.253.11:443

And the Response Headers is:

Allow:OPTIONS, TRACE, GET, HEAD, POST
Content-Length:0
Date:Mon, 27 Mar 2017 11:09:45 GMT
Public:OPTIONS, TRACE, GET, HEAD, POST
Server:Microsoft-IIS/8.5

This looks like IIS 8.5 is responding to the preflight request.

To try and prevent this in IIS I have added into web.config the following:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="false">
      <remove name="FormsAuthenticationModule" />
      <remove name="WebDavModule" />
    </modules>
    <handlers>
      <remove name="WebDav" />
      <remove name="OPTIONS" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <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>
    <rewrite>
        <rules>
            <rule name="Strategy to RedSlim" stopProcessing="true">
                <match url="^strategy" />
                <action type="Rewrite" url="framework/RedSlim/web/" />
            </rule>
        </rules>
    </rewrite>
    <httpProtocol>
        <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type: application/json; charset=UTF-8, Accept, CSRF_NONCE" />
        <add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, OPTIONS" />
        <add name="Access-Control-Max-Age" value="1000" />
    </customHeaders>
    </httpProtocol>
    <httpErrors errorMode="Detailed" />
    <security>
        <authorization>
            <remove users="" roles="Users" verbs="GET" />
            <add accessType="Allow" users="?" roles="" verbs="GET, POST" />
        </authorization>
            <requestFiltering>
                <alwaysAllowedUrls>
                    <add url="//p.staging.c.com" />
                    <add url="//digitalworkplace.staging.c.com" />
                </alwaysAllowedUrls>
                <verbs>
                    <add verb="OPTIONS" allowed="true" />
                    <add verb="POST" allowed="true" />
                </verbs>
            </requestFiltering>
    </security>
    </system.webServer>
</configuration>

It seems to me that something is wrong with the IIS setup.

In Chrome I can see the POST request header as below but then no response.

Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Access-Control-Request-Headers:access-control-allow-headers, access-control-allow-methods, access-control-allow-origin, content-type, csrf_nonce
Access-Control-Request-Method:POST
Connection:keep-alive
Host:digitalworkplace.staging.c.com
Origin:http://p.staging.c.com
        Referer:http://p.staging.c.com/pagesUTF8/auftrag_allgemeinauftrag.jsp?OSG08=24370
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

Does anyone have any suggestion of what else I need to do to allow the POST request to function after the preflight?

JawasUK
  • 11
  • 3
  • Please use https://stackoverflow.com/posts/43045870/edit to edit/update the question and copy+paste the response headers from the OPTIONS response into the question. You need to look at those response headers to know what the value of the Access-Control-Allow-Headers response header is. – sideshowbarker Mar 27 '17 at 12:39
  • I have edited my question to remove the response headers from the ajax call. The OPTIONS Response Headers are still the same – JawasUK Mar 27 '17 at 12:49
  • Allow:OPTIONS, TRACE, GET, HEAD, POST Content-Length:0 Date:Mon, 27 Mar 2017 12:45:03 GMT Public:OPTIONS, TRACE, GET, HEAD, POST Server:Microsoft-IIS/8.5 – JawasUK Mar 27 '17 at 12:50
  • OK yeah I see what you’re saying now—your IIS server isn’t actually sending any `Access-Control-Allow-*` response headers at all in the response for the OPTIONS request. To fix that, you probably want to look at https://stackoverflow.com/questions/12458444/enabling-cross-origin-resource-sharing-on-iis7/14631068#14631068 and other existing answers here and try those – sideshowbarker Mar 27 '17 at 12:54

0 Answers0