Implementing Resource Level Throttling for Each User on Each Resource in WSO2 API Manager 4.0.0

Dinuka Caldera
6 min readMar 6, 2023

--

First I would like to explain the exact requirement. What you can achieve using this blog article. Using that you will be able to decide whether you should read the article further or not.

I hope everyone who read this article have some knowledge about WSO2 API Manager . If you want to know more about API Manager , go to the https://apim.docs.wso2.com/en/4.0.0/get-started/overview/ .

Lets get back the with the requirement, lets say there are 3 users (User A, User B, User C) who has access to the same API ( example API) and there are 3 resources in the API ( Resource A , Resource B, Resource C)

User A :

  • should only be able to send 2 requests (Max) per minute to “Resource A”
  • should only be able to send 4 requests (Max) per minute to “Resource B”
  • should only be able to send 6 requests (Max) per minute to “Resource C”

User B :

  • should only be able to send 1 requests (Max) per minutes to “Resource A”
  • should only be able to send 5 requests (Max) per minute to “Resource B”
  • should only be able to send 7 requests (Max) per minute to “Resource C”

User C :

  • should only be able to send 3 requests (Max) per minutes to “Resource A”
  • should only be able to send 6 requests (Max) per minute to “Resource B”
  • should only be able to send 9 requests (Max) per minute to “Resource C”

This requirement can be achieved using “Advanced Rate Limiting Policies”.

To learn more about Advanced Rate Limiting Policies, please refer to [1] documentation. In brief, using these advanced rate limiting policies, we can control access to the API or API resources based on the following properties and their combinations:

  • IP address and address range: You can control/restrict access to your API or its selected resources for a given IP address or address range.
  • HTTP REQUEST HEADERS: Apply limits to APIs by filtering requests based on HTTP headers.
  • JWT CLAIMS: Advanced throttling policies based on JWT claims allow you to filter requests by JWT claim values and apply limits for requests.
  • QUERY PARAMETERS: Filtering based on query parameters almost always applies to HTTP GET requests when doing search-type operations. For example, if you have a search API with category as a query parameter, you can have different limits for searching different categories.

As I mentioned earlier, to get an in-depth understanding of these advanced throttling policies, please refer to [1] documentation. In this scenario, we need a property to identify each user who sends an API request, so that we can filter out the user based on that property. As you all know, in general, when sending an API request, you have to do it with an Access Token. WSO2 API Manager uses JSON Web Tokens (JWTs) as access tokens to provide secure access to APIs.

These JWT Access Tokens contain JWT claims. JWT claims are pieces of information encoded into a JSON Web Token (JWT) to represent information about the authenticated user or client.

Here’s an example of some common JWT claims that might be included in a JWT access token:

  • “iss”: The issuer of the token, typically the authorization server.
  • “sub”: The subject of the token, typically the user ID or client ID.
  • “aud”: The audience of the token, typically the API or resource server.
  • “exp”: The expiration time of the token.
  • “nbf”: The time before which the token must not be accepted.
  • “iat”: The time at which the token was issued.
  • “jti”: The unique identifier for the token.

I will explain this using a JWT token that I have used for API invocation. In the below scenario, I have made an API invocation. As you can see, I have included the JWT Access token for the curl request under the Authorization header. When you decode this JWT token using [2], you will be able to find the JWT claims under the payload. I have explained the meanings of these claims above.

curl -X GET “https://localhost:8243/pizzashack/1.0.0/menu" -H “accept: application/json” -H “Authorization: Bearer eyJ4NXQiOiJNell4TW1Ga09HWXdNV0kwWldObU5EY3hOR1l3WW1NNFpUQTNNV0kyTkRBelpHUXpOR00wWkdSbE5qSmtPREZrWkRSaU9URmtNV0ZoTXpVMlpHVmxOZyIsImtpZCI6Ik16WXhNbUZrT0dZd01XSTBaV05tTkRjeE5HWXdZbU00WlRBM01XSTJOREF6WkdRek5HTTBaR1JsTmpKa09ERmtaRFJpT1RGa01XRmhNelUyWkdWbE5nX1JTMjU2IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJkaW51a2EiLCJhdXQiOiJBUFBMSUNBVElPTiIsImF1ZCI6Ingwd3lTMjl0UHlUS0lUNWRaZVB6VThCX1lUMGEiLCJuYmYiOjE2NzgwODU3NzMsImF6cCI6Ingwd3lTMjl0UHlUS0lUNWRaZVB6VThCX1lUMGEiLCJzY29wZSI6ImRlZmF1bHQiLCJpc3MiOiJodHRwczpcL1wvbG9jYWxob3N0Ojk0NDNcL29hdXRoMlwvdG9rZW4iLCJleHAiOjE2NzgwODkzNzMsImlhdCI6MTY3ODA4NTc3MywianRpIjoiMGVmZDMyYjAtODA5ZC00NjUwLTg1NDItOWVjM2ExMjU3YTdlIn0.aVdXN0csjlRdeMkNZkvUANEekdmVNv-_1L31t37qkcr8vw86XF6wCW4kUMhWKURH69ng9XFXHzgqSFSlo7f7KnaiybMG15frXsUe9H2tntB-E8-bhJ4Y1H7rvOj8NalhzE3sqCNp9w9R2J3GsI-z4_efS5hLdpFONLN_jU9YL_ZdXJfWd0diUEVL1o4UHnLWNZUof4E0GLa4TE8nyYiSyw9sUAwhm8DdL60Y31C3F9O94ODSMlwc-s384jJrrEme9VC2LbofKIZb3JjEwfNMyrSNKFO8zNL5h8hmBuz9KYj-IREL97MKcEvchDIHselm1QdQ94pKQySjJr3x6BuaJQ

Decoded jwt payload :

“sub”: “dinuka”,
“aut”: “APPLICATION”,
“aud”: “x0wyS29tPyTKIT5dZePzU8B_YT0a”,
“nbf”: 1678085773,
“azp”: “x0wyS29tPyTKIT5dZePzU8B_YT0a”,
“scope”: “default”,
“iss”: “https://localhost:9443/oauth2/token",
“exp”: 1678089373,
“iat”: 1678085773,
“jti”: “0efd32b0–809d-4650–8542–9ec3a1257a7e”

Through which claim do you think we can achieve our requirement? Yes, you are correct! 😃 It is the sub-claim that we can use.

A “sub” claim represents the subject of the token, typically the user ID or client ID. In the above scenario, it’s Dinuka (the username I used to log in to the developer portal to get the access token).

So now we have a way to identify each user. 😃😃

Now let’s go back to creating an advanced level throttling policy to achieve the requirement. Before starting the API Manager, you need to make some configuration changes in the <Product_Home>/repository/conf/deployment.toml file. Please open that file and add the following configurations. You can find more details about these configurations in [1] documentation.

[apim.throttling]
enable_jwt_claim_based_throttling=true

[apim.jwt]
enable = true
#encoding = “base64” # base64,base64url
#generator_impl = “org.wso2.carbon.apimgt.keymgt.token.JWTGenerator”
claim_dialect = “http://wso2.org/claims"
#convert_dialect = false
#header = “X-JWT-Assertion”
#signing_algorithm = “SHA256withRSA”
#enable_user_claims = true
#claims_extractor_impl = “org.wso2.carbon.apimgt.impl.token.ExtendedDefaultClaimsRetriever”

Now I will show the next steps using screenshots , it will be easier for you to follow the steps.

1.) We can “Add New Policy” through the admin portal of the API Manager. After starting the API Manager, please log in to the admin portal and click on “Advanced Policies” as shown below.

2.) Click on “Add New Policy” and fill in the required details (Please refer to the screenshot below). You will see the “Default Limit” option, which is the general limit for every request for that resource (for example, 20 requests per 1 minute). I have added a policy named “ThrottleForResourceA”.

3.) Click on “Add Conditional Group”. In there, you can see the JWT Condition Policy. This policy filters the user using the “sub” attribute in the access token.

(Sub is the username of the user who logs in to the developer portal, as I explained before.)
Please refer to the image below.
In the screenshot, you can see that I have defined that user1 can send 3 requests per 1 minute. (In these example screenshots, I have used 3 users: user 1, user 2, and user 3. For each user, you have to add a conditional group )

4.) Add another condition group for user2 and define 6 requests per 1 minute

5.) Add another condition group for user3 and define 10 requests per 1 minute

6.) Then save the policy, Go to the publisher portal, Go to the relevant resource and select the added policy from Rate Limiting policy ( Refer 6.png image)

I have only provided the steps to add an Advanced Policy for one resource (Resource A). For the other two resources (Resource B and Resource C), you have to add new policies by following the same steps depending on the requirements.

[1] https://apim.docs.wso2.com/en/4.0.0/design/rate-limiting/adding-new-throttling-policies/#adding-a-new-advanced-rate-limiting-policy

[2] https://jwt.io/

--

--

Dinuka Caldera

👨‍💻 Software Engineer at WSO2 | 🎓 Computer Science Graduate from University of Colombo | 💡 Problem Solver | 🌄 Adventure Enthusiast | 🌿 Nature Lover