Skip to content

Commit 8c2e3ed

Browse files
authored
[WAF] Use JWT claims in custom rules (and rate limiting rules) (#17629)
1 parent c08469f commit 8c2e3ed

File tree

2 files changed

+37
-13
lines changed

2 files changed

+37
-13
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
pcx_content_type: configuration
3+
title: Issue challenge for admin user in JWT claim based on attack score
4+
head:
5+
- tag: title
6+
content: Issue challenge for admin user in JWT claim based on attack score
7+
---
8+
9+
:::note
10+
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.
11+
:::
12+
13+
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/).
14+
15+
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.
16+
17+
- **Expression**: `(lookup_json_string(http.request.jwt.claims["<TOKEN_CONFIGURATION_ID>"][0], "user") eq "admin" and cf.waf.score < 40)`
18+
- **Action**: _Managed Challenge_
19+
20+
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.

src/content/docs/waf/rate-limiting-rules/parameters.mdx

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,27 +36,27 @@ Set of parameters defining how Cloudflare tracks the request rate for the rule.
3636

3737
Use one or more of the following characteristics:
3838

39-
| Dashboard value | API value | Notes |
40-
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
41-
| N/A(implicitly included) | `cf.colo.id`(mandatory) | [Do not use in expressions](#do-not-use-cfcoloid-as-a-field-in-expressions) |
42-
| IP | `ip.src` | [Incompatible with **IP with NAT support**](#incompatible-characteristics) |
43-
| IP with NAT support | `cf.unique_visitor_id` | [Incompatible with **IP**](#incompatible-characteristics) |
44-
| **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) |
45-
| **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) |
46-
| **Query value of** (enter parameter name) | `http.request.uri.args["<query_param_name>"]` | [Missing field versus empty value](#missing-field-versus-empty-value) |
39+
| Dashboard value | API value | Notes |
40+
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
41+
| N/A(implicitly included) | `cf.colo.id`(mandatory) | [Do not use in expressions](#do-not-use-cfcoloid-as-a-field-in-expressions) |
42+
| IP | `ip.src` | [Incompatible with **IP with NAT support**](#incompatible-characteristics) |
43+
| IP with NAT support | `cf.unique_visitor_id` | [Incompatible with **IP**](#incompatible-characteristics) |
44+
| **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) |
45+
| **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) |
46+
| **Query value of** (enter parameter name) | `http.request.uri.args["<query_param_name>"]` | [Missing field versus empty value](#missing-field-versus-empty-value) |
4747
| **Host** | `http.host` |
4848
| **Path** | `http.request.uri.path` |
4949
| **AS Num** | `ip.geoip.asnum` |
5050
| **Country** | `ip.geoip.country` |
5151
| **JA3 Fingerprint** | `cf.bot_management.ja3_hash` |
5252
| **JA4** | `cf.bot_management.ja4` |
53-
| **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) |
54-
| **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) |
55-
| **Form input value of** (enter field name) | `http.request.body.form["<input_field_name>"]` | [Missing field versus empty value](#missing-field-versus-empty-value) |
56-
| **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/) |
53+
| **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) |
54+
| **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) |
55+
| **Form input value of** (enter field name) | `http.request.body.form["<input_field_name>"]` | [Missing field versus empty value](#missing-field-versus-empty-value) |
56+
| **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/) |
5757
| **Body** | `http.request.body.raw` |
5858
| **Body size** (select operator, enter size) | `http.request.body.size` |
59-
| **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/) |
59+
| **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/) |
6060

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

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

226+
### Requirements for using claims inside a JSON Web Token (JWT)
227+
228+
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.
229+
226230
## Configuration restrictions
227231

228232
- 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.

0 commit comments

Comments
 (0)