HmacCsrfGuard
HMAC-SHA256 {@see CsrfGuardInterface}: a token is a base64url-encoded JSON payload (`route`, `issuedAt`, `expiresAt`, `nonce`, `signature`) whose `signature` binds the payload to the session id it was issued for via `hash_hmac('sha256', $sessionId . "\n" . json_encode($payload), $secret)`. Stateless — no storage, no server-side lookup — verification is pure recomputation-and-compare with {@see hash_equals()}. A token issued for one session/route pair fails verification for any other. One key per page (greenhouse decisions/0211): the page's boot carries ONE token, so every endpoint the page talks to must verify with the SAME `$secret` — the house's `live.secret`, configured by the host. A guest plugin never derives its own; a token issued under one secret is garbage to a guard holding another.
HmacCsrfGuard::__construct()
public function __construct(string $secret, int $ttlSeconds = 3600, int $clockSkewSeconds = 30, ?Closure $clock = null):Parameters
| Name | Type | Description |
|---|---|---|
| $secret | string | the house's `live.secret` — one per page, shared by every guard and signer on it |
| $ttlSeconds | int | how long an issued token lives |
| $clockSkewSeconds | int | tolerance either side of `issuedAt`/`expiresAt` |
| $clock | (\Closure(): int | null) | injectable clock for expiry tests; defaults to `time()` |
HmacCsrfGuard::issueToken()
public function issueToken(string $sessionId, string $route): stringIssues a new HMAC-signed token bound to `$sessionId` and `$route`, valid for `$ttlSeconds` from now.
Parameters
| Name | Type | Description |
|---|---|---|
| $sessionId | string | |
| $route | string |
HmacCsrfGuard::verifyToken()
public function verifyToken(string $token, string $sessionId, string $route): boolVerifies `$token` was issued by {@see issueToken()} for this exact `$sessionId`/`$route` pair and has not expired (within the configured clock-skew tolerance). Returns `false` — never throws — for a malformed, mismatched, or expired token.
Parameters
| Name | Type | Description |
|---|---|---|
| $token | string | |
| $sessionId | string | |
| $route | string |
HmacCsrfGuard::remaining()
public function remaining(string $token): intSeconds until `$token`'s own `expiresAt` — `0` once expired, and `0` for a token that cannot be decoded. Unverified: it reads the payload, it does not check the signature.
Parameters
| Name | Type | Description |
|---|---|---|
| $token | string |
HmacCsrfGuard::ttl()
public function ttl(): intThe lifetime every issued token starts with, in seconds.