Specification

Vord external token format — v0

Status: DRAFT — v0, unstable. This specification is normative once implemented (RFC 2119 keywords) but the v0 format itself carries no stability promise: it may change without migration support until it is stamped stable, which happens only when a second, non-reference verifier or a sustained conformance run validates it (ADR-0003). Tokens minted under v0 are proof-of-concept artifacts, not durable commitments.

This document specifies the external token — the OIDC ID / access token a relying party or Vör verifies. Rationale lives in the ADRs (0003, 0010, 0044); this spec states only what an implementation MUST do. The companion artifact is the status-list spec.

1. Envelope

  1. A token is a JOSE JWT in compact serialization (header.payload.signature), OIDC-conformant. No other serialization is valid in v0.
  2. The signature algorithm is EdDSA (Ed25519) or ES256. A verifier MUST reject alg: none and MUST reject any alg value other than the one bound to the token's kid (§2.2) — algorithms are never negotiated from the token.

2. Header parameters

Parameter Requirement
alg REQUIRED. EdDSA or ES256 in v0. MUST match the kid binding (§2.2).
kid REQUIRED. Identifies the signing key in the realm's published key material (ADR-0023). A token without kid MUST be rejected.
typ REQUIRED. JWT (or the OIDC-mandated media type for the token's role).

2.2 Per-kid algorithm binding

The realm's published key material binds each kid to exactly one algorithm. A verifier MUST resolve the token's kid, then verify with the bound algorithm — never with the token's claimed alg alone. A kid absent from the current key material MUST cause rejection (this absence is the emergency kill switch of ADR-0036).

3. Claims

3.1 Standard claims (REQUIRED unless noted)

iss (the realm's issuer URL), sub (the principal's immutable internal id, ADR-0011 — never a mutable identifier), aud, exp, iat, nbf (OPTIONAL). Temporal claims are evaluated against the verifier's trusted clock within the shared skew window (ADR-0033, ADR-0039).

3.2 Vord claims — active in v0

Claim Requirement
vfmt REQUIRED. The token-format version, the integer 0 in v0. A verifier MUST reject a vfmt it does not implement (ADR-0003 decision 5).
sid REQUIRED on tokens minted from a session or refresh-token family. The session id (ADR-0016, ADR-0044): the unit of session logout and back-channel logout.
amr / acr REQUIRED. Authentication methods and assurance level achieved at issuance (ADR-0015, ADR-0020). v0 issuers emit at least amr: ["pwd"] and a realm-default acr.
status REQUIRED. The status-list reference covering this token: the list URI and this token's index (see the status-list spec §4). A verifier that enforces revocation MUST resolve it against its cached list.

3.3 Reserved seats — names registered in v0, semantics deferred

These claims/parameters MUST NOT be emitted with other meanings and MUST be ignored (not rejected) by v0 verifiers when absent:

  • cnf — proof-of-possession / DPoP confirmation (ADR-0014, ADR-0025).
  • groups / roles and the overage marker — group memberships and app-role assignments under the bounded-claim discipline of ADR-0045: an issuer MUST NOT emit an unbounded membership list; the modes are omit, filtered (client-registered subset), or capped-with-overage-marker.
  • act and the impersonation acr value — the composite-identity actor claim and its floor assurance level (proposal 0026); a verifier that ignores act sees a valid, low-assurance token, which is the safe reading.
  • Composite-alg values — a single classical+PQC composite signature suite (ADR-0042); registered as future alg values, not a second signature.
  • Attenuation (biscuit) tokens are a separate reserved format, not a JWT claim (ADR-0003 decision 3).

4. Size budget

An issued token SHOULD NOT exceed 4 KiB in compact serialization — the ceiling relying parties may assume for cookie and header transport. PQC composite signatures (ADR-0042) will pressure this budget; a v-next raising it is an ecosystem event, not a quiet change.

5. Verification procedure (normative summary)

A verifier, given a token, the realm's cached key material, a trusted clock, and the cached status list (all per ADR-0010 — no other inputs):

  1. Parse the compact JWT; reject on malformed structure.
  2. Reject if vfmt is absent or unimplemented.
  3. Resolve kid in the cached key material; reject if absent; verify the signature with the bound algorithm; reject alg mismatch or alg: none.
  4. Validate exp / nbf / iat against the trusted clock ± the skew window.
  5. Resolve the status reference against the cached status list, which MUST itself be fresh per the status-list spec; reject if the token's index is revoked, its kid is in the key-revocation set, or its sid is revoked.
  6. Validate iss / aud per OIDC.

Steps 1–6 complete with no read of any strongly-consistent domain (constitution rule 1); the freshness of the cached inputs bounds the guarantee (ADR-0010 §2, ADR-0039).

6. Conformance

Conformance vectors live under conformance/ and are exercised in CI (cargo xtask conformance). Every MUST above corresponds to at least one accept- or reject-vector; the first vectors land with the reference implementation (vord-format).