azurejwtpolicyquotaapim

APIM quota-by-key policy when condition JWT subject


I have an API which is currently secured using the validate-jwt policy. The output token I get from a variable and want to give different quotas to different customers, for this I am using the "subject" of the JWT to identify. This seems to work if I have quota-by-key in the inbound policy with no when condition and a counter key of the JWT subject (jwt-token being my output token from validate-jwt policy). After 5 calls I get a 403 Quota Exceeded in my postman test:

<quota-by-key calls="5" renewal-period="86400" counter-key="@(((Jwt)context.Variables["jwt-token"]).Subject)" />

If I then try to embed this in a when condition so based on the subject I want to give them different quotas I can't seem to get that to work. I have tried for example:

<when condition="@(((Jwt)context.Variables["jwt-token"]).Subject == "MYSUBJECTSTRING")">
                <quota-by-key calls="5" renewal-period="86400" counter-key="@(((Jwt)context.Variables["jwt-token"]).Subject)" />
            </when>

and also the below as "Subject" is defined on MS as string (so using Equals):

<when condition="@(((Jwt)context.Variables["jwt-token"]).Subject.Equals("MYSUBJECTSTRING"))">
                <quota-by-key calls="5" renewal-period="86400" counter-key="@(((Jwt)context.Variables["jwt-token"]).Subject)" />
            </when>

None of these work and I can go way over the 5 calls. This is all with the same token so Subject is the same...in fact the token was valid for 24 hours so the same token was used to do all this testing.

Anyone got any ideas or had any similar problems?

Lastly I know the "proper" solution is to use Products and apply the policies there but I only have a few customers and wanted to try this without having the overhead of setting up Products etc.

Thanks!


Solution

  • Use when condition in <choose></choose>.

    I am able to get the expected response by using the given policy.

    <policies>
        <inbound>
            <base />
            <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized" require-expiration-time="true" require-scheme="Bearer" require-signed-tokens="true">
                <openid-config url="https://login.microsoftonline.com/{tenantId}/v2.0/.well-known/openid-configuration" />
                <issuers>
                    <issuer>https://sts.windows.net/{tenantId}/</issuer>
                </issuers>
            </validate-jwt>
            <set-variable name="jwt-token" value="@(context.Request.Headers.GetValueOrDefault("Authorization").AsJwt())" />
            <choose>
                <when condition="@(((Jwt)context.Variables["jwt-token"]).Subject == "{Subject}")">
                    <quota-by-key calls="5" renewal-period="300" counter-key="@(((Jwt)context.Variables["jwt-token"]).Subject)" />
                </when>
            </choose>
        </inbound>
    </policy>
    

    enter image description here enter image description here

    enter image description here