Skip to content

Claims and tokens

Anvil\Endpoint\ComponentClaims describes what a token grants:

Parameter Type Meaning
component string component id, e.g. admin:triage:tickets
panel string panel id; the token only works in this panel
tenantId ?int the current tenant, service('tenantContext')->id(); the token only works in this tenant
record ?Uuid optional record the component works on
context array<string, scalar|null> optional server defined values, e.g. a parent UUID; other values throw
use Anvil\Data\Uuid;
use Anvil\Endpoint\ComponentClaims;
$claims = new ComponentClaims(
component: $this->panel->id() . ':' . $this->slug() . ':title',
panel: $this->panel->id(),
tenantId: service('tenantContext')->id(),
record: Uuid::fromString($uuid),
context: ['mode' => 'compact'],
);
$token = service('componentTokens')->issue($claims);

In the handler, the claims are $request->claims:

  • $request->claims->record is the record the token was issued for. Take the record from there, never from the input, when the component belongs to one record.
  • $request->claims->context holds the context values.
  • actions() also receives the claims, so the available actions can depend on them.

Tokens are encrypted and bound to the session, so the browser can neither read nor change the claims. They expire after Config\Anvil::$componentTokenTtl (default two hours); every answer that renders the component again should issue a new token, as render() does in the example. Details: Component tokens.

Context values are fixed by the server when the token is issued and cannot be changed by the browser – use them for values the component needs on every request but must not trust from the input:

// Issuing: the component shows the comments of one ticket in "compact" mode.
new ComponentClaims(
component: 'admin:tickets:comments',
panel: 'admin',
tenantId: service('tenantContext')->id(),
record: $ticketUuid,
context: ['mode' => 'compact', 'parent' => $projectUuid->toString()],
);
// Handling
$mode = (string) ($request->claims->context['mode'] ?? 'full');
$parent = Uuid::fromString((string) $request->claims->context['parent']);

Only scalars and null are allowed; keep the context small, it is part of every token in the page.

A request with an expired token answers 403 with “The page has expired. Please reload it.” as a toast. Polling elements marked with data-anvil-poll stop quietly instead, see Events and refreshing. Expired tokens are not logged as security events; altered or foreign tokens are (access.denied).