Skip to content

Commit

Permalink
[WAF] Use JWT claims in custom rules (and rate limiting rules) (#17629)
Browse files Browse the repository at this point in the history
  • Loading branch information
pedrosousa authored Oct 18, 2024
1 parent c08469f commit 8c2e3ed
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
pcx_content_type: configuration
title: Issue challenge for admin user in JWT claim based on attack score
head:
- tag: title
content: Issue challenge for admin user in JWT claim based on attack score
---

:::note
To use claims inside a JSON Web Token (JWT), you must first set up a [token validation configuration](/api-shield/security/jwt-validation/configure/) in API Shield.
:::

This example configures additional protection for requests with a JSON Web Token (JWT) with a user claim of `admin`, based on the request's [attack score](/waf/detections/attack-score/).

Create a custom rule that issues a Managed Challenge if the user claim in a JWT is `admin` and the attack score is below 40.

- **Expression**: `(lookup_json_string(http.request.jwt.claims["<TOKEN_CONFIGURATION_ID>"][0], "user") eq "admin" and cf.waf.score < 40)`
- **Action**: _Managed Challenge_

In this example, `<TOKEN_CONFIGURATION_ID>` is your [token configuration ID](/api-shield/security/jwt-validation/configure/) found in JWT Validation and `user` is the JWT claim.
30 changes: 17 additions & 13 deletions src/content/docs/waf/rate-limiting-rules/parameters.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,27 @@ Set of parameters defining how Cloudflare tracks the request rate for the rule.

Use one or more of the following characteristics:

| Dashboard value | API value | Notes |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| N/A(implicitly included) | `cf.colo.id`(mandatory) | [Do not use in expressions](#do-not-use-cfcoloid-as-a-field-in-expressions) |
| IP | `ip.src` | [Incompatible with **IP with NAT support**](#incompatible-characteristics) |
| IP with NAT support | `cf.unique_visitor_id` | [Incompatible with **IP**](#incompatible-characteristics) |
| **Header value of** (enter header name) | `http.request.headers["<header_name>"]` | [Use lowercased header name in API](#use-a-lowercased-header-name-for-api-users) and [Missing field versus empty value](#missing-field-versus-empty-value) |
| **Cookie value of** (enter cookie name) | `http.request.cookies["<cookie_name>"]` | [Recommended configurations](#recommended-configurations-when-using-cookie-value-of) and [Missing field versus empty value](#missing-field-versus-empty-value) |
| **Query value of** (enter parameter name) | `http.request.uri.args["<query_param_name>"]` | [Missing field versus empty value](#missing-field-versus-empty-value) |
| Dashboard value | API value | Notes |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| N/A(implicitly included) | `cf.colo.id`(mandatory) | [Do not use in expressions](#do-not-use-cfcoloid-as-a-field-in-expressions) |
| IP | `ip.src` | [Incompatible with **IP with NAT support**](#incompatible-characteristics) |
| IP with NAT support | `cf.unique_visitor_id` | [Incompatible with **IP**](#incompatible-characteristics) |
| **Header value of** (enter header name) | `http.request.headers["<header_name>"]` | [Use lowercased header name in API](#use-a-lowercased-header-name-for-api-users) and [Missing field versus empty value](#missing-field-versus-empty-value) |
| **Cookie value of** (enter cookie name) | `http.request.cookies["<cookie_name>"]` | [Recommended configurations](#recommended-configurations-when-using-cookie-value-of) and [Missing field versus empty value](#missing-field-versus-empty-value) |
| **Query value of** (enter parameter name) | `http.request.uri.args["<query_param_name>"]` | [Missing field versus empty value](#missing-field-versus-empty-value) |
| **Host** | `http.host` |
| **Path** | `http.request.uri.path` |
| **AS Num** | `ip.geoip.asnum` |
| **Country** | `ip.geoip.country` |
| **JA3 Fingerprint** | `cf.bot_management.ja3_hash` |
| **JA4** | `cf.bot_management.ja4` |
| **JSON string value of** (enter key) | `lookup_json_string(http.request.body.raw, "<key>")` | [Missing field versus empty value](#missing-field-versus-empty-value) and [`lookup_json_string()` function reference](/ruleset-engine/rules-language/functions/#lookup_json_string) |
| **JSON integer value of** (enter key) | `lookup_json_integer(http.request.body.raw, "<key>")` | [Missing field versus empty value](#missing-field-versus-empty-value) and [`lookup_json_integer()` function reference](/ruleset-engine/rules-language/functions/#lookup_json_integer) |
| **Form input value of** (enter field name) | `http.request.body.form["<input_field_name>"]` | [Missing field versus empty value](#missing-field-versus-empty-value) |
| **JWT claim of** (enter token configuration ID, claim name) | `lookup_json_string(http.request.jwt.claims["<token_configuration_id>"][0], "<claim_name>")` | [Missing field versus empty value](#missing-field-versus-empty-value) and [JWT Validation reference](/api-shield/security/jwt-validation/transform-rules/) |
| **JSON string value of** (enter key) | `lookup_json_string(http.request.body.raw, "<key>")` | [Missing field versus empty value](#missing-field-versus-empty-value) and [`lookup_json_string()` function reference](/ruleset-engine/rules-language/functions/#lookup_json_string) |
| **JSON integer value of** (enter key) | `lookup_json_integer(http.request.body.raw, "<key>")` | [Missing field versus empty value](#missing-field-versus-empty-value) and [`lookup_json_integer()` function reference](/ruleset-engine/rules-language/functions/#lookup_json_integer) |
| **Form input value of** (enter field name) | `http.request.body.form["<input_field_name>"]` | [Missing field versus empty value](#missing-field-versus-empty-value) |
| **JWT claim of** (enter token configuration ID, claim name) | `lookup_json_string(http.request.jwt.claims["<token_configuration_id>"][0], "<claim_name>")` | [Requirements for claims in JWT](#requirements-for-using-claims-inside-a-json-web-token-jwt), [missing field versus empty value](#missing-field-versus-empty-value) and [JWT Validation reference](/api-shield/security/jwt-validation/transform-rules/) |
| **Body** | `http.request.body.raw` |
| **Body size** (select operator, enter size) | `http.request.body.size` |
| **Custom** (enter expression) | Enter a custom expression. You can use a function such as `substring()` or `lower()`, or enter a more complex expression. | [Functions](/ruleset-engine/rules-language/functions/) |
| **Custom** (enter expression) | Enter a custom expression. You can use a function such as `substring()` or `lower()`, or enter a more complex expression. | [Functions](/ruleset-engine/rules-language/functions/) |

The available characteristics depend on your Cloudflare plan. Refer to [Availability](/waf/rate-limiting-rules/#availability) for more information.

Expand Down Expand Up @@ -223,6 +223,10 @@ If you use **Cookie value of** as a rate limiting rule characteristic, follow th
- Create a [custom rule](/waf/custom-rules/) that blocks requests with more than one value for the cookie.
- Validate the cookie value at the origin before performing any demanding server operations.

### Requirements for using claims inside a JSON Web Token (JWT)

To use claims inside a JSON Web Token (JWT), you must first set up a [token validation configuration](/api-shield/security/jwt-validation/configure/) in API Shield.

## Configuration restrictions

- If the rule expression [includes IP lists](/waf/tools/lists/use-in-expressions/), you must enable the **Also apply rate limiting to cached assets** parameter.
Expand Down

0 comments on commit 8c2e3ed

Please sign in to comment.