Enabling CORS in Umbraco API with Azure

Overcome CORS policy challenges in Umbraco CMS 8 API when integrated with Azure. This comprehensive guide helps developers swiftly configure and resolve CORS issues.

Introduction: Understanding CORS in Umbraco and Azure#

While developing with Umbraco API, you might face CORS policy hurdles, especially when consuming the API from another domain.

Dive deep into this guide to seamlessly enable and fix CORS issues in Umbraco API and Azure WebApp.

CORS policy problem I faced#

Recently, I was struggling with the local angular app while retrieving the data from the Umbraco API endpoint.

The app was throwing the following error:

Access to XMLHttpRequest at ‘http://testapi.umbracare.net/umbraco/API/showcase/getdummydata’ from origin ‘http://localhost:4200’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status

You may have encountered this problem as well because this is a very common error which means the CORS mechanism was not properly configured.

Why CORS Issues Arise#

Below you have great recap from Microsoft official site:

Browser security prevents a web page from making AJAX requests to another domain. This restriction is called the same-origin policy and prevents a malicious site from reading sensitive data from another site. However, sometimes you might want to let other sites call your web API. Cross-Origin Resource Sharing (CORS) is a W3C standard that allows a server to relax the same-origin policy. Using CORS, a server can explicitly allow some cross-origin requests while rejecting others. CORS is safer and more flexible than earlier techniques such as JSONP.

Let's break down the quotation piece by piece for a comprehensive understanding:

"Browser security prevents a web page from making AJAX requests to another domain."

This means that for security reasons, web browsers are designed to prohibit web pages from sending requests to a different domain (website) than the one the web page originated from.

This is especially relevant for AJAX (Asynchronous JavaScript and XML) requests, which allow data exchange with a server and updating parts of a web page without reloading the whole page.

"This restriction is called the same-origin policy and prevents a malicious site from reading sensitive data from another site."

The "same-origin policy" is a security mechanism implemented by web browsers.

It ensures that scripts on one web page (or from one domain) can't access or modify the data of another web page (from a different domain).

This policy is crucial to prevent malicious websites from retrieving sensitive information from another site that a user might be logged into, like banking or email sites.

"However, sometimes you might want to let other sites call your web API."

Despite the same-origin policy's security benefits, there are legitimate scenarios where you'd want a web page from one domain to access the API (Application Programming Interface) of another domain.

For instance, third-party apps or widgets must fetch data from another site's API.

"Cross-Origin Resource Sharing (CORS) is a W3C standard that allows a server to relax the same-origin policy."

To accommodate the need for controlled cross-domain interactions, the W3C (World Wide Web Consortium) introduced CORS.

It's a protocol that enables servers to specify who (which origins) can access their assets or APIs, effectively providing a way to bypass the same-origin policy in a controlled manner.

"Using CORS, a server can explicitly allow some cross-origin requests while rejecting others."

With CORS, a server can be selective.

For example, if you have an API, you might allow requests from specific trusted domains while blocking others.

This gives server administrators control and flexibility.

"CORS is safer and more flexible than earlier techniques such as JSONP."

Before CORS, developers used workarounds like JSONP (JSON with Padding) to achieve cross-domain requests.

JSONP has potential security vulnerabilities, like exposing sites to cross-site script injection attacks.

CORS was introduced as a standardized, safer, and more flexible alternative, allowing servers to handle cross-origin requests with specific rules and without the risks associated with older methods.

In summary, while browsers block web pages from making requests to different domains for security reasons (same-origin policy), there are times when such interactions are needed.

CORS is a standard that allows servers to specify and control these interactions securely, making it a safer and more versatile solution compared to earlier methods.

Setting up CORS in Umbraco#

1. Installing Microsoft AspNet Cors library:

  • Launch Visual Studio.
  • Navigate to Tools > Nuget Package Manager > Package Manager Console.
  • Execute the command: Install-Package Microsoft.AspNet.WebApi.Cors.

2. Enabling CORS Globally:

For Umbraco CMS v8 and above, leverage the composing technique:

  • Craft a WebApiCorsComponent.
  • Develop a WebApiCorsComposer to connect with the WebApiCorsComponent.
  • During the component's initialization, invoke GlobalConfiguration.Configuration.EnableCors().

Here's a sample code to get you started:

[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
internal class WebApiCorsComposer : IComposer
{
   public void Compose(Composition composition)
   {
      composition.Components().Insert<WebApiCorsComponent>();
   }

   public class WebApiCorsComponent : IComponent
   {
      public void Initialize()
      {
         GlobalConfiguration.Configuration.EnableCors();
      }

      public void Terminate()
      {
      }
   }
}

3. Implementing EnableCors Attribute:

  • First, import the System.Web.Http.Cors namespace.
  • Decorate the desired controller or action with the EnableCors attribute, as illustrated below:
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class ShowcaseApiController : UmbracoApiController
{
    [HttpGet]
    public IHttpActionResult GetDummyData()
    {
        return Json("ok");
    }
}

4. Configuring HTTP Methods and Headers:

<httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By" />
        <remove name="Server" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD" />
        <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Accept, Authorization, Content-Type" />
      </customHeaders>
</httpProtocol>

You may skip setting headers and methods in web.config end specify them directly in Component with the following code:

var cors = new EnableCorsAttribute(origins: "*",
   headers: "Origin, X-Requested-With, Accept, Authorization, Content-Type", 
   methods: "GET, POST, PUT, DELETE, OPTIONS");

GlobalConfiguration.Configuration.EnableCors(cors);
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
internal class WebApiCorsComposer : IComposer
{
   public void Compose(Composition composition)
   {
      composition.Components().Insert<WebApiCorsComponent>();
   }

   public class WebApiCorsComponent : IComponent
   {
      public void Initialize()
      {
         var cors = new EnableCorsAttribute(origins: "*",
            headers: "Origin, X-Requested-With, Accept, Authorization, Content-Type", 
            methods: "GET, POST, PUT, DELETE, OPTIONS");

         GlobalConfiguration.Configuration.EnableCors(cors);
      }

      public void Terminate()
      {
      }
   }
}

Final step: Enabling CORS for Azure WebApp#

When deploying Azure Web App Service, it’s crucial to specify the origins allowed to make cross-origin calls due to Azure's stringent security configurations.

A commonly overlooked step is that even when the API is deployed, CORS might pose challenges if not configured correctly.

Steps to Enable CORS in Azure WebApp:

  1. Access the Azure portal.
  2. Proceed to the App services segment.
  3. Locate and select your app service.
  4. Navigate to the CORS subsection.
  5. Insert the origin. For local development, use "http://localhost:4200".
  6. Commit the changes by saving the new configurations.

For unrestricted domain access, input “*” and ensure all other origins are removed from the list.

Enabling Cors for Azure App Service

Enabling Cors for Azure App Service

Conclusion#

Tackling CORS policy challenges in Umbraco API combined with Azure doesn't have to be daunting.

By following this guide meticulously, developers can effortlessly integrate and operate across different domains.

Encountered further issues or need expert assistance? 

Contact us for personalized guidance and swift resolutions.

↑ Top ↑