s.sekhar
s.sekhar

Reputation: 1

How to make Azure API Management (API Gateway) CORS policy dynamic?

I want to add domains(Origins) in allowed-origins section dynamically in Azure API gateway. Is it possible ? Or is there another way we can setup the CORS, so that we can allow origins dynamically.

    <cors>
        <allowed-origins>
            <origin>http://www.example.com</origin>
        </allowed-origins>
        <allowed-methods>
            <method>GET</method>
            <method>POST</method>
        </allowed-methods>
    </cors>

Upvotes: 0

Views: 1686

Answers (3)

Equestre
Equestre

Reputation: 121

I found the solution above to not work with preflight OPTIONS requests, since then only the CORS policy is evaluated, resulting in it trying to evaluate an unassigned variable.

I solved it by creating (in this example 2) Named Values, containing a comma-separated list of URLs. The Named Values are available at the time of policy evaluation and will therefore work. The reasoning behind multiple lists is that named values have a size limitation of 4096 characters (my source here is the error message in Azure portal when putting in a too-big value), which isn't very many URLs. I have opted to use CSV instead of a JSON array as the data structure in the Named Values due to the overhead that is added when dealing with JSON. I ran some benchmarks locally and the concatenation of CSV lists where approx 3 times faster with lower memory allocation and GC.

    <cors>
        <allowed-origins>
            <origin>@{
                string[] stringArray = new string[] { {{corslistcsv0}}, {{corslistcsv1}} };
                string origin = context.Request.Headers.GetValueOrDefault("Origin", "");
                int urlIndex = -1;
                urlIndex = Array.IndexOf(stringArray, origin);
                return urlIndex == -1 ? "https://urlthaticontrol.org" : origin;
            }</origin>
        </allowed-origins>
    </cors>

Here is an example list in a Named Value:

"https://url1.com","http://url2.net","http://url3.org"

Upvotes: 1

s.sekhar
s.sekhar

Reputation: 1

I found one way that I'm mentioning bellow.

<inbound>
    <base />
    <send-request mode="new" response-variable-name="variable" timeout="600" ignore-error="true">
        <set-url>@("http://MyDomain/ApiMethod?Origin="(string)context.Request.Headers["Origin"].Last())</set-url>
        <set-method>GET</set-method>
        <set-body />
    </send-request>
    <cors>
        <allowed-origins>
            <origin>@((string)((IResponse)context.Variables["variable"]).Body.As<JObject>(true)["Origin"])</origin>
        </allowed-origins>
        <allowed-methods>
            <method>GET</method>
            <method>POST</method>
        </allowed-methods>
    </cors>
</inbound
  • First called a API which takes the Origin as query parameter.
  • stored the response in variable parameter.
  • API Returns Json Object eg: { "Origin": "http://www.example.com" }
  • Form the response I retrieve the Origin Value. and assign it to <origin></origin>

Upvotes: 0

Vitaliy Kurokhtin
Vitaliy Kurokhtin

Reputation: 7810

You can't dynamically add elements to policy configuration, but you can dynamically provide values for them (https://learn.microsoft.com/en-us/azure/api-management/api-management-policy-expressions):

<cors>
    <allowed-origins>
        <origin>@(context.Request.Url.ToUri().GetLeftPart(UriPartial.Authority))</origin>
    </allowed-origins>
    <allowed-methods>
        <method>GET</method>
        <method>POST</method>
    </allowed-methods>
</cors>

Upvotes: 1

Related Questions