API Index — Namespaces, Packages, Reports, Indices
CsrfMiddleware
in package
implements
MiddlewareInterface
CSRF Protection Middleware.
Generates a per-session CSRF token on safe requests (GET/HEAD/OPTIONS)
and validates it on state-changing requests (POST/PUT/PATCH/DELETE).
Token sources checked (first match wins):
$_POST['_csrf_token'](form hidden field)X-CSRF-Tokenrequest header (AJAX/htmx)
The token is stored in $g->session['_csrf_token'] and exposed via
$g->memo['csrf_token'] for templates to read.
Usage in app.php:
$app->addMiddleware(new CsrfMiddleware());
In templates:
<input type="hidden" name="_csrf_token" value="<?= $g->memo['csrf_token'] ?>">
With htmx:
<body hx-headers='{"X-CSRF-Token": "<?= $g->memo['csrf_token'] ?>"}'>
To exempt paths (e.g. webhooks):
$app->addMiddleware(new CsrfMiddleware(exempt: ['/api/webhook', '/api/stripe']));
Table of Contents
Interfaces
- MiddlewareInterface
Constants
- FIELD_NAME : mixed = '_csrf_token'
- HEADER_NAME : mixed = 'X-CSRF-Token'
- SAFE_METHODS : mixed = ['GET', 'HEAD', 'OPTIONS']
- TOKEN_LENGTH : mixed = 32
Properties
- $exempt : array<int, string>
Methods
- __construct() : mixed
- process() : ResponseInterface
- Generate or validate the CSRF token for the current request.
- pathMatchesExempt() : bool
- Segment-boundary exemption match (#342).
Constants
FIELD_NAME
private
mixed
FIELD_NAME
= '_csrf_token'
HEADER_NAME
private
mixed
HEADER_NAME
= 'X-CSRF-Token'
SAFE_METHODS
private
mixed
SAFE_METHODS
= ['GET', 'HEAD', 'OPTIONS']
TOKEN_LENGTH
private
mixed
TOKEN_LENGTH
= 32
Properties
$exempt
private
array<int, string>
$exempt
URL path prefixes that skip CSRF validation.
Methods
__construct()
public
__construct([array<int, string> $exempt = [] ]) : mixed
Parameters
- $exempt : array<int, string> = []
-
URL prefixes to skip validation (e.g.
['/api/webhook']).
process()
Generate or validate the CSRF token for the current request.
public
process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
Safe methods (GET/HEAD/OPTIONS) and exempt path prefixes pass through
without validation. All other methods require a matching token submitted
via the _csrf_token POST field or the X-CSRF-Token header; a mismatch
or missing token returns a 403 response immediately.
Parameters
- $request : ServerRequestInterface
- $handler : RequestHandlerInterface
Return values
ResponseInterfacepathMatchesExempt()
Segment-boundary exemption match (#342).
private
static pathMatchesExempt(string $path, string $prefix) : bool
An exempt entry exempts the request path only on an exact match or a
true path-segment boundary — NOT a loose str_starts_with prefix. So
'/api/stripe' exempts /api/stripe and /api/stripe/charge, but
NEVER /api/stripeKeyUpdate (the historical CSRF-bypass: an attacker
appended text to an exempt prefix to skip validation on a sibling
state-changing route). Same class of fix as the #232 ScopedMiddleware
segment-safe scope. A trailing-slash entry ('/api/stripe/') keeps its
prefix semantics for the subtree below it (the next char after the
prefix is already the / boundary).
Parameters
- $path : string
- $prefix : string