Home > Back-end >  In API Management Policy, check if a header value is within a list/array
In API Management Policy, check if a header value is within a list/array

Time:07-27

I have an API management inbound policy where I can grab a users id from within a JWT. For the purpose of some testing, I then want API management to check in the policy, "Is this ID within the list of tester IDs that are allowed to access here"

<policies>
    <inbound>
        <base />
        <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
            <openid-config url="myurl" />
        </validate-jwt>
        <set-header name="header-value-userId" exists-action="override">
            <value>@(context.Request.Headers.GetValueOrDefault("Authorization").AsJwt()?.Claims.GetValueOrDefault("oid"))</value>
        </set-header>
        <!--
        PSEUDOCDOE below to describe my intention
        How can I check that the abover header-value-userId value is within a hardcoded list at this point?
        
        @{
            string[] userList = ["user1", "user2", "user3"];

            var match = userList.FirstOrDefault(x => x.Contains(header-value-userId));

            if(match == null)
                return bad request
        }
        -->
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

Thanks for any help.

--- UPDATE ---

Thanks to the answer from Markus Meyer I now have this working. See below my now full working example.

<policies>
    <inbound>
        <base />
        <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
            <openid-config url="myurl" />
        </validate-jwt>
        <set-variable name="isValidUser" value="@{

            var email = context.Request.Headers.GetValueOrDefault("Authorization").AsJwt()?.Claims.GetValueOrDefault("emails");

            string[] emailList = new string[] { "[email protected]", "[email protected]" };

            var match = emailList.Any(x => x.Contains(email));

            if(match == true)
            {
                return true;
            }
            
            return false;
        }" />
        <choose>
            <when condition="@(context.Variables.GetValueOrDefault<bool>("isValidUser") == false)">
                <return-response>
                    <set-status code="401" reason="Unauthorized" />
                    <set-header name="Content-Type" exists-action="override">
                        <value>application/json</value>
                    </set-header>
                    <set-body>@("{\"status\": \""   "User not valid"   "\"}")</set-body>
                </return-response>
            </when>
            <otherwise>
                <return-response>
                    <set-status code="200" reason="Valid" />
                    <set-header name="Content-Type" exists-action="override">
                        <value>application/json</value>
                    </set-header>
                    <set-body>@("{\"status\": \""   "User valid"   "\"}")</set-body>
                </return-response>
            </otherwise>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

CodePudding user response:

Using the choose policy allows you to check a boolean condition.
In the current example, the condition is set in the set-variable policy

return-response will return your wanted response.

Complete example:

<policies>
    <inbound>
        <base />
        <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
            <openid-config url="myurl" />
        </validate-jwt>
        <set-header name="header-value-userId" exists-action="override">
            <value>@(context.Request.Headers.GetValueOrDefault("Authorization").AsJwt()?.Claims.GetValueOrDefault("oid"))</value>
        </set-header>
        <set-variable name="isValidUser" value="@{
            string[] userList = new string[] { "user1", "user2", "user3" };
            var match = userList.FirstOrDefault(x => x.Contains("header-value-userId"));
            if(match == null)
            {
                return true;
            }
            
            return false;
        }" />
        <choose>
            <when condition="@(context.Variables.GetValueOrDefault<bool>("isValidUser") == false)">
                <return-response>
                    <set-status code="401" reason="Unauthorized" />
                    <set-header name="Content-Type" exists-action="override">
                        <value>application/json</value>
                    </set-header>
                    <set-body>@("{\"status\": \""   "User not valid"   "\"}")</set-body>
                </return-response>
            </when>
        </choose> 
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

A few things to note:

This this the correct code for the string[]:

string[] userList = new string[] { "user1", "user2", "user3" };

There's no need to store the usereId into the header. The value can also be stored in a variable.

  • Related