Enable cross-origin requests in UmbracoApiController and Azure

What you will learn

In this article, I’ll show how you can resolve Umbraco cms API CORS policy problems.

By the end of this short tutorial, you will know what steps you need to take to:

  • Configure Cors for Umbraco API
  • Fix Umbraco API CORS issues
  • Use Umbraco API from another domain
  • Consume Umbraco API hosted on Azure

The problem

In my case, my local angular app was throwing the following error while consuming data from the Umbraco API controller:

Access to XMLHttpRequest at 'http://testapi.piotrbach.com/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 error as well.

Why this is happening?

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. This tutorial shows how to enable CORS in your Web API application.

What to do now?

Install Microsoft AspNet Cors library using nuget

  • Open Visual Studio
  • Go to Tools\Nuget Package Manager
  • Choose Package Manager Console
  • Install the package as follows: Install-Package Microsoft.AspNet.WebApi.Cors

Decorate controller or action with EnableCors attribute

Before that - include System.Web.Http.Cors namespace

[EnableCors(origins: "*", headers: "*", methods: "*")]
public class ShowcaseApiController : UmbracoApiController
{
    [HttpGet]
    public IHttpActionResult GetDummyData()
    {
        return Json("ok");
    }
}

Enable CORS globally

To do so in Umbraco CMS v8+ you can use composing technique :

  • Create WebApiCorsComponent
  • Create WebApiCorsComposer and wire up the WebApiCorsComponent
  • Execute GlobalConfiguration.Configuration.EnableCors() during component initialization (inside Initialize() method)
public class WebApiCorsComposer : ComponentComposer<WebApiCorsComponent>
{

}

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

    public void Terminate()
    {
    }
}

Modify Web.config

<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()
      {
      }
   }
}

Enabling CORS for Azure WebApp

If you're using Azure Web App - additionally, you may need to specify the exact origins that should be allowed to make cross-origin calls.

Due to Azure security settings, you must add the domains that can access the app.

I noticed that many guys forget this step and once the app is ready - it's still not working.

To do so you need to take the following steps:

  • Open Azure portal
  • Go to App services
  • Find the app service
  • Go to CORS section
  • Add origin, in my case "http://localhost:4200"
  • Save new settings

Azure Umbraco CMS Web app enabling CORS

References:

https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api

Comments
Leave a Comment