Search code examples
javascriptcorsdynamics-crmdynamics-crm-365

Enable CORS on CRM365 (on-premises)


I would like to retrieve data from a Microsoft Dynamics CRM 365 site which is not available online (i.e. via Azure AD) from a single page web application using JavaScript. But all the requests to the CRM server are blocked by the browser as the CRM server does not send the correct CORS headers allowing my webserver to retrieve data. There are tutorials available explaining how to connect using Azure, but they don't apply in my environment.

(Just statically sending Access-Control-Allow-Origin: * is probably not enough as I need to authenticate and using a wildcard is not supported when using authentication afaik.)

Is there a way to use CORS with a local CRM 365?


Solution

  • After lots of trying and some help from other websites, I think I found the solution:

    Dynamics CRM 365 does not care about the CORS issue, nor does it add the necessary headers for people who need them for their requests.

    In order to get the headers, they have to be added at web server (IIS) level using the HTTP Response Headers or be added to the web.config file in the website's directory on the file sytem.

    If authentication is needed on the Dynamics CRM system, the header Access-Control-Allow-Origin is not allowed to have the value * (wildcard). The value of this header needs to match the calling server's URL, which means that the web server has to dynamically change the header value for Access-Control-Allow-Origin depending on the calling server's host name. (I found this information on https://kamranicus.com/cors-multiple-origins-iis/)

    You also need to add the header Access-Control-Allow-Credentials and set its value to true for Authentication to work properly.

    If you need to send additional headers to the CRM system with the request, you need to add those headers to the Access-Control-Allow-Headers response header in order to tell the client browser which headers are allowed to be sent along with the request.

    Here's what I have now and what's working on my end:

       <configuration>
         ...
         <location>
           <system.webServer>
             ...
             <httpPrococol>
               <customHeaders>
                 <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
                 <add name="Access-Control-Allow-Headers" value="Content-Type, Authorization, Prefer" />
                 <add name="Access-Control-Allow-Credentials" value="true" />
               </customHeaders>
             </httpProtocol>
             <rewrite>
               <outboundRules>
                 ...
                 <rule name="AddCrossDomainHeader">
                   <match serverVariable="RESPONSE_Access_Control_Allow_Origin" pattern=".*" />
                   <conditions logicalGrouping="MatchAll" trackAllCaptures="true">
                     <add input="{HTTP_ORIGIN}" pattern="(http(s)?:\/\/((.+\.)?mydomain\.com))" />
                   </conditions>
                   <action type="Rewrite" value="{C:0}" />
                 </rule>           
               </outboundRules>
             </rewrite>
           </system.webServer>
         </location>
         ...
       </configuration>
    

    I hope that this also helps others having the same problems as I had.