Configuring Mapped Throttling

This section describes how to configure a mapped throttling policy, where the grouping policy defines criteria to group requests, and the rate policy defines the criteria by which rates are mapped.

The following image illustrates how different throttling rates can be applied to users.

The following image illustrates how each user with a gold status has a throttling rate of 6 requests/10 seconds, and each user with a silver status has 3 requests/10 seconds. The bronze status is not mapped to a throttling rate, and so a user with the bronze status has the default rate.

Mapped Throttling
Mapped Throttling

Configure Mapped Throttling
  1. Set up AM:

    1. Set up AM as described in "Validating Access_Tokens Through the Introspection Endpoint".

    2. Select Scripts > OAuth2 Access Token Modification Script, and replace the default script as follows:

      import org.forgerock.http.protocol.Request
      import org.forgerock.http.protocol.Response
      
      def attributes = identity.getAttributes(["mail", "employeeNumber"].toSet())
      accessToken.setField("mail", attributes["mail"][0])
      def mail = attributes['mail'][0]
      if (mail.endsWith('@example.com')) {
        status = "gold"
      } else if (mail.endsWith('@other.com')) {
        status = "silver"
      } else {
        status = "bronze"
      }
      accessToken.setField("status", status)

      The AM script adds user profile information to the access_token, and defines the content of the users status field according to the email domain.

  2. Set up IG:

    1. Set an environment variable for the IG agent password, and then restart IG:

      $ export AGENT_SECRET_ID='cGFzc3dvcmQ='

      The password is retrieved by a SystemAndEnvSecretStore, and must be base64-encoded.

    2. Add the following route to IG:

      $HOME/.openig/config/routes/00-throttle-mapped.json
      %appdata%\OpenIG\config\routes\00-throttle-mapped.json
      {
        "name": "00-throttle-mapped",
        "baseURI": "http://app.example.com:8081",
        "condition": "${matches(request.uri.path, '^/home/throttle-mapped')}",
        "heap": [
          {
            "name": "SystemAndEnvSecretStore-1",
            "type": "SystemAndEnvSecretStore"
          },
          {
            "name": "AmService-1",
            "type": "AmService",
            "config": {
              "agent": {
                "username": "ig_agent",
                "passwordSecretId": "agent.secret.id"
              },
              "secretsProvider": "SystemAndEnvSecretStore-1",
              "url": "http://openam.example.com:8088/openam/",
              "version": "7"
            }
          }
        ],
        "handler": {
          "type": "Chain",
          "config": {
            "filters": [
              {
                "name": "OAuth2ResourceServerFilter-1",
                "type": "OAuth2ResourceServerFilter",
                "config": {
                  "scopes": [
                    "mail",
                    "employeenumber"
                  ],
                  "requireHttps": false,
                  "realm": "OpenIG",
                  "accessTokenResolver": {
                    "name": "token-resolver-1",
                    "type": "TokenIntrospectionAccessTokenResolver",
                    "config": {
                      "amService": "AmService-1",
                      "providerHandler": {
                        "type": "Chain",
                        "config": {
                          "filters": [
                            {
                              "type": "HttpBasicAuthenticationClientFilter",
                              "config": {
                                "username": "ig_agent",
                                "passwordSecretId": "agent.secret.id",
                                "secretsProvider": "SystemAndEnvSecretStore-1"
                              }
                            }
                          ],
                          "handler": "ForgeRockClientHandler"
                        }
                      }
                    }
                  }
                }
              },
              {
                "name": "ThrottlingFilter-1",
                "type": "ThrottlingFilter",
                "config": {
                  "requestGroupingPolicy": "${contexts.oauth2.accessToken.info.mail}",
                  "throttlingRatePolicy": {
                    "name": "MappedPolicy",
                    "type": "MappedThrottlingPolicy",
                    "config": {
                      "throttlingRateMapper": "${contexts.oauth2.accessToken.info.status}",
                      "throttlingRatesMapping": {
                        "gold": {
                          "numberOfRequests": 6,
                          "duration": "10 s"
                        },
                        "silver": {
                          "numberOfRequests": 3,
                          "duration": "10 s"
                        },
                        "bronze": {
                          "numberOfRequests": 1,
                          "duration": "10 s"
                        }
                      },
                      "defaultRate": {
                        "numberOfRequests": 1,
                        "duration": "10 s"
                      }
                    }
                  }
                }
              }
            ],
            "handler": "ReverseProxyHandler"
          }
        }
      }

      For information about how to set up the IG route in Studio, see "Mapped Throttling Filter in Structured Editor".

      Notice the following features of the route:

      • The route matches requests to /home/throttle-mapped.

      • The OAuth2ResourceServerFilter validates requests with the AccessTokenResolver, and makes it available for downstream components in the oauth2 context.

      • The ThrottlingFilter bases the request grouping policy on the AM user's email. The throttling rate is applied independently to each email address.

        The throttling rate is mapped to the AM user's status, which is defined by the email domain, in the AM script.

  3. Test the setup:

    1. Get an access_token for George from AM:

      $ george_token=$(curl -s \
      --user "client-application:password" \
      --data "grant_type=password&username=george&password=C0stanza&scope=mail%20employeenumber" \
      http://openam.example.com:8088/openam/oauth2/access_token | jq -r ".access_token")

    2. Using the access_token for authentication, access the route multiple times. The following example accesses the route 10 times, and writes the output to a file:

      $ curl -v http://openig.example.com:8080/home/throttle-mapped/\[01-10\] --header "Authorization:Bearer ${george_token}" > /tmp/george.txt 2>&1

    3. Search the output file to see the result:

      $ grep "< HTTP/1.1" /tmp/george.txt | sort | uniq -c
      
      6 < HTTP/1.1 200
      4 < HTTP/1.1 429

      Notice that with a gold status, George can access the route 6 times in 10 seconds.

    4. In AM, change George's email to george@other.com, and then run the last two steps again to see how the access is reduced.

Considerations for Dynamic Throttling

The following image illustrates what can happen when the throttling rate defined by throttlingRateMapping changes frequently or quickly:

Dynamic Throttling Rate
Dynamic throttling rate

In the image, George starts out with a gold status. In a two second period, he sends five requests, is downgraded to silver, sends four requests, is upgraded back to gold, and then sends three more requests.

After making five requests with a gold status, George has almost reached his throttling rate. When his status is downgraded to silver, those requests are disregarded and the full throttling rate for silver is applied. George can now make three more requests even though he had nearly reached his throttling rate with a gold status.

After making three requests with a silver status, George has reached his throttling rate. When he makes a fourth request, the request is refused.

George is now upgraded back to gold and can now make six more requests even though he had reached his throttling rate with a silver status.

When you configure requestGroupingPolicy and throttlingRateMapper, bear in mind what happens when the throttling rate defined by the throttlingRateMapper is changed.

Read a different version of :