Passing Input to Azure APIM Policy Fragment

Shaikh Zaki Mohammed
3 min readJan 21, 2024

Azure APIM policy fragment enables you to define policy once and use it till eternity. In this article, we will understand the creation of a policy fragment and a way to pass input to them.

In continuation of this article Creating Validate JWT Policy in Azure APIM, where we have created policies related to validate-jwt as in bound or using fragment. Keeping that as a reference point let’s begin with the showdown.

We can find a descriptive and beautifully documented guide about how to create a policy fragment from here , it covers below pointers:

While all this covers most of it, but one aspect is missed with such arrangement that we can’t pass parameters to the fragments from policy. Let us bridge this gap by identifying a way to supply parameters to fragments.

For this we will first bring one fragment from the previous article and get started with:

<fragment>
<!-- policy -->
<validate-jwt
header-name="Authorization"
failed-validation-httpcode="401"
failed-validation-error-message="Unauthorized"
require-scheme="Bearer"
output-token-variable-name="output-token">

<openid-config url="https://login.microsoftonline.com/contoso.onmicrosoft.com/v2.0/.well-known/openid-configuration/" />

<audiences>
<audience>f0047ad9-83fb-4a82-8167-d253b0dfb0c3</audience>
<audience>08c06aea-ea55-48d4-9611-a43c53bf0955</audience>
</audiences>

<issuers>
<issuer>https://login.microsoftonline.com/31537af4-6d77-4bb9-a681-d2394888ea26/v2.0</issuer>
</issuers>
</validate-jwt>

<!-- custom-headers -->
<choose>
<when condition='@(!string.IsNullOrEmpty((string)((Jwt)context.Variables["output-token"]).Claims.GetValueOrDefault("username")))'>
<set-header name="CO-Username" exists-action="override">
<value>@((string)((Jwt)context.Variables["output-token"]).Claims.GetValueOrDefault("username"))</value>
</set-header>
</when>
</choose>
<choose>
<when condition='@(!string.IsNullOrEmpty((string)((Jwt)context.Variables["output-token"]).Claims.GetValueOrDefault("email")))'>
<set-header name="CO-Email" exists-action="override">
<value>@((string)((Jwt)context.Variables["output-token"]).Claims.GetValueOrDefault("email"))</value>
</set-header>
</when>
</choose>
</fragment>

Here, we are having validate-jwt policy with openid, audiences, issuers and we are setting 2 custom headers namely CO-Username and CO-Email with “CO-” as prefix (CO = CodeOmelet) which is obtained by the validate-jwt policy once verified with output variable “output-token”.

Here, we have a policy code base where inside the inbound section we are including the previously created fragment “ValidateJwtFragment”.

Now, if I want to supply an audience through the policy code base then I won’t be able to as the “include-fragment” tag doesn’t have such attribute. Instead, we can try a hack by creating a Policy Variable and accessing it in the fragment dynamically (using policy expression, C# way).

Let us see that in action:

<policies>
<inbound>
<base />
<set-variable name="audience" value="938c1d33-5075-474c-b91a-1b539388ab54" />
<include-fragment fragment-id="ValidateJwtFragment" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>

Here, we create a policy variable using “set-variable” tag with attribute name as “audience” and its associated value. We will now use this in the fragment using the policy expression.

<policies>
<inbound>
<base />
<set-variable name="audience" value="938c1d33-5075-474c-b91a-1b539388ab54" />
<include-fragment fragment-id="ValidateJwtFragment" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>

Here, we are using the Policy Expression to access the audience variable and supplying it to the audience tag, notice with the ternary else condition we are providing some default audience value as it needs to contain some value instead of empty audience. The ContainsKey method checks if the audience variable exists or not, the explicit typecasting is needed while accessing the variables.

By using the Policy Variable and Policy Expression we can easily supply and consume any input parameters to a policy fragment. Note that this approach might not be a fit for all situation, feel free to provide your input if you have come across some other way to do this.

Below are the references taken from Microsoft Azure documentation:

Git Repository

Check out the git repository for this project or download the code.

Git Repository

Summary

Azure APIM is vast topic and have lot of areas to talk about. One of its important areas is the policy it offers. Such policies come up with challenges too, one of such challenge we have addressed using an alternate approach with the help of policy variable and expression, that was unable to pass input params to fragment. Stay tuned for more such articles!

Hope this article helps.

Originally published at https://codeomelet.com.

--

--

Shaikh Zaki Mohammed

Learner, developer, coder and an exceptional omelet lover. Knows how to flip arrays or omelet or arrays of omelet.