Setting Up CORS With Azure API Manager

When using Azure API Manager, one of it’s benefits is the ability to respond to certain API requests without having to ping your backend for the response. Essentially short circuiting API responses and offloading that computer power to a simple API management layer. In this case, we are specifically talking about being able to respond to a browser’s OPTIONS request (e.g. using CORS), without your entire application pipeline kicking into gear.

Now like most things, there are multiple ways to achieve the same result. So we are first going to talk about how we can get API manager to respond to the request without involving your backend API at all, but later we will also show you how you can allow a pass through to your API if you prefer to manage CORS configuration inside your application code, rather than API manager.

Using A CORS Policy

If you’re looking for the most hands off approach possible, your best bet is to use a CORS Inbound Policy within APIM. Previously, you had to manage most of this via XML copy and paste, but now there is an easy configuration wizard to follow. Inside Azure API Manager, select your API, All Operations, then go ahead and select “Add Policy” on Inbound processing.

On the next screen, find the option to “Allow cross-origin resource sharing (CORS)” as shown below

By default, the options presented to you will only be to select the “Allowed origins”, which is defaulted to *. I highly recommend instead to select the “Full” options and complete them. If you use Basic, by default, it will only allow GET and POST requests. This might be OK for some API’s, but generally modern applications make use of things like PUT, DELETE and PATCH.

After saving the configuration on this screen, your API manager will actually “short circuit” all OPTIONS requests and respond with these options defined here. Meaning that your backend service never has to put in computing power for trivial requests again!

Under the hood, using this wizard actually just adds the following custom policy to the inbound policy XML :

<cors>
  <allowed-origins>
    <origin>*</origin>
  </allowed-origins>
  <allowed-methods>
    <method>GET</method>
    <method>POST</method>
    <method>PUT</method>
    <method>DELETE</method>
  </allowed-methods>
</cors>

You may find guides around Azure API manager that still refer to pasting in this XML manually via the Azure Portal, and it’s still a valid way to do it, but for the most part Azure has added a tonne of quick wizards that essentially do the same thing, but don’t involve you having to do janky notepad copy and pastes all over the place.

Using A Wildcard OPTIONS Request

This is actually the default when you add a backend service like an Azure App Service to APIM via the wizard, instead of mapping each endpoint manually. When you do this, it actually creates a wildcard OPTIONS operation that does nothing but pass every request to your backend.

If this wildcard operation doesn’t show for you, simply create a new operation for OPTIONS that has a wildcard URL as depicted above.

After doing this, it will be up to your application to respond to OPTIONS requests. This means that your application is now getting hit when APIM could take the load off for you, but it does mean that you have more fine grain control if you prefer to manage CORS from within your existing application code rather than Azure API Manager.

Map Individual OPTIONS Requests

Instead of using a wildcard operation inside APIM, you can of course map each endpoint individually. In some cases this may be more effort than it’s worth but if you want complete fine grain control over what requests are forward to your application, this is an option.

I personally try and avoid this as it it essentially means duplicating each request to add an OPTIONS operation. If you are looking at doing this for security reasons, then in my opinion the use of a CORS inbound policy, and making the attack surface area be handled by Azure API Manager, is a much better option.

Leave a Reply

Your email address will not be published. Required fields are marked *