Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/common-attacks.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,13 +368,13 @@ $config->allow2ban->add('volume-ban',

### API Key Throttling

Rate-limit by API key for authenticated endpoints:
Rate-limit by API key for authenticated endpoints. `hashedHeader()` stores a sha256 fingerprint of the key in the cache backend rather than the raw value:

```php
$config->throttles->add('api-key',
limit: 1000,
period: 60,
key: KeyExtractors::header('X-Api-Key'),
key: KeyExtractors::hashedHeader('X-Api-Key'),
);
```

Expand Down
5 changes: 3 additions & 2 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -1048,12 +1048,13 @@ $config->allow2ban->add('high-volume-ban',
key: KeyExtractors::ip()
);

// Ban by API key for authenticated routes
// Ban by API key for authenticated routes. hashedHeader() stores a sha256
// fingerprint of the key in the ban registry instead of the raw credential.
$config->allow2ban->add('api-key-ban',
threshold: 1000,
period: 60,
banSeconds: 300,
key: KeyExtractors::header('X-Api-Key')
key: KeyExtractors::hashedHeader('X-Api-Key')
);
```

Expand Down
6 changes: 4 additions & 2 deletions docs/features/fail2ban.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,13 +349,15 @@ Ban API keys that exceed expected usage. Unlike rate limiting (which returns 429
```php
use Flowd\Phirewall\KeyExtractors;

// Ban any API key that makes more than 1000 requests in 60 seconds
// Ban any API key that makes more than 1000 requests in 60 seconds.
// hashedHeader() stores the sha256 fingerprint instead of the raw key so the
// ban registry doesn't carry the credential verbatim.
$config->allow2ban->add(
name: 'api-key-abuse',
threshold: 1000,
period: 60,
banSeconds: 300, // 5 minute ban
key: KeyExtractors::header('X-Api-Key'),
key: KeyExtractors::hashedHeader('X-Api-Key'),
);
```

Expand Down
5 changes: 4 additions & 1 deletion docs/features/rate-limiting.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,13 +216,16 @@ Phirewall ships with common key extractors for typical rate limiting scenarios:
|--------|-------------|---------|
| `KeyExtractors::ip()` | Client IP from `REMOTE_ADDR` | `?string` |
| `KeyExtractors::clientIp($resolver)` | Client IP via trusted proxy resolver | `?string` |
| `KeyExtractors::header('X-User-Id')` | Value of a specific header | `?string` |
| `KeyExtractors::header('X-User-Id')` | Raw value of a specific header | `?string` |
| `KeyExtractors::hashedHeader('X-Api-Key')` | sha256 fingerprint of a header value | `?string` |
| `KeyExtractors::method()` | HTTP method (uppercase) | `?string` |
| `KeyExtractors::path()` | Request path (always returns a value, never skips) | `string` |
| `KeyExtractors::userAgent()` | User-Agent header value | `?string` |

All extractors except `path()` return `null` when the value is missing or empty, which causes the throttle rule to be skipped for that request.

Prefer `hashedHeader()` over `header()` whenever the header carries a credential (`Authorization`, `Cookie`, `X-Api-Key`, …). The cache backend and ban registry then store the sha256 fingerprint rather than the raw secret, so anyone with read access to the cache cannot recover the credential.

### Custom Key Extractors

Write your own closure for any logic:
Expand Down
Loading