Skip to content

Token and claim reference

GenAuth's delegation model uses two kinds of token. Their roles are different and so are their field shapes — confusing the two is the single most common integration mistake:

Delegate tokenAccess token (after exchange)
What it isAn authorization record: who delegated what to which agent, and for how longAn access credential: what the agent actually presents to a resource
Who consumes itGenAuth (for token exchange and validation)Your target resource service
Where it comes fromIssued after consent completes (see Quickstart)Exchanged from a delegate token (RFC 8693)
Has act?NoYes (a GenAuth extension — see below)

Both are JWTs (RFC 7519) and are verified the standard way.

Table 1: complete delegate token fields

A JWT whose token_type is eak_delegation_token. Thirteen top-level fields:

FieldTypeMeaningContract level
token_typestringAlways eak_delegation_tokenImplementation detail — fine for recognizing the token kind, but the value may change across versions; do not hard-code an equality check as your only test
issstringIssuerStable contract
substringThe delegating user's ID — the subject of a delegate token is always a personStable contract
azpstringThe access key ID that started the delegationStable contract
agent_idstringThe agent the authority was delegated toStable contract
scopestring[]Granted scopes (formatted service.capability:action, e.g. webagent.web_search:run)Stable contract
audstringAlways genauth:token-exchange — a delegate token is only accepted by the token exchange endpointStable contract
eak_tenant_idstringThe owning workspace IDStable contract
genauth_userpool_idstringThe user pool the user belongs toImplementation detail — this field is known to be subject to a rename; resource-side code must not depend on it. Treat the version noted on this page as authoritative
resource_bindingsobjectProduct resources bound to the workspace (e.g. { gumem: { project_id }, webagent: { tenant_id } })Implementation detail
jtistringUnique token IDStable contract
grant_idstringThe grant record ID (spans the authorization lifecycle)Stable contract
audit_idstringAudit chain ID (see Audit and accountability chain)Stable contract

A delegate token has no act claim

act only appears in the exchanged access token. If you are looking for act in a delegate token, you are holding the wrong token.

Table 2: extra fields on the exchanged access token

The access token returned by token exchange (POST /api/v3/eak/token-exchange) carries these GenAuth extension fields in addition to the target resource's standard claims:

FieldTypeMeaning
actobjectThe actor: { "type": "eak_delegation", "agent_id": "...", "grant_id": "...", "access_key_id": "..." }
exchange_idstringUnique ID for this exchange (enters the audit chain)
product_resourceobjectThe bound target resource, shaped { "type": "gumem_project" | "webagent_tenant", "id": "..." }. This is an object, not a string — do not compare it directly against "gumem"

act is a GenAuth extension, not the RFC 8693 shape

RFC 8693 defines act as a nested sub ("act": { "sub": "..." }). GenAuth's act is an extension object with a type discriminator — resource-side code must explicitly check act.type === "eak_delegation" rather than parsing the standard nested shape. The full resource-side checklist is in Protect your APIs.

The sub of the access token is still the user — "on whose behalf" always points to a person, and "who is acting" is expressed by act. That is where delegation semantics land inside the token.

Migration and the compatibility window

Two shapes are deprecated on the SDK side (marked @deprecated as of @eazo/anima v0.2.1):

OldNew
delegateAgent({ ... })delegateToken({ ... })
top-level userId: "usr_x"user: { id: "usr_x" }

A two-track compatibility window

The server-side API still accepts the top-level userId during the compatibility window. That means: even after your own code has fully migrated to user: { id }, anyone holding your access key can still start a delegation with the old parameter. Treat access key custody and rotation as your first line of defense — threat analysis in Security considerations.

Validating a token

  • Online validation (recommended): POST /api/v3/eak/delegations/introspect with { "token": "..." }. A valid token returns { "active": true, ...all claims }; anything invalid or expired returns { "active": false }. The SDK equivalent is anima.genauth.introspectDelegationToken({ token }).
  • Local verification: after standard JWT signature verification, always check aud (always genauth:token-exchange for a delegate token) and expiry. For access tokens, the resource side must also check the scope intersection (see Protect your APIs).

Next steps