Token exchange request/response schema
See Token API for the full endpoint reference. resource and scope are
required here even though RFC 8693 makes them optional in general — a hop token that
doesn't name exactly one target and one data class wouldn't be a narrowing, which is the only
thing this endpoint exists to produce.
TokenExchangeRequest
| Field | Type | Notes |
|---|---|---|
grant_type | literal | urn:ietf:params:oauth:grant-type:token-exchange |
subject_token | str | |
subject_token_type | literal | urn:ietf:params:oauth:token-type:jwt |
resource | str (max 512) | Required |
scope | str (max 128) | Required |
actor_token / actor_token_type | str | null | Optional today; required once identity proof-of-possession ships |
audience | str | null |
TokenExchangeResponse
| Field | Type |
|---|---|
access_token | str |
issued_token_type | urn:ietf:params:oauth:token-type:jwt |
token_type | Bearer |
expires_in | int |
scope | str |
OAuthError (RFC 6749 §5.2)
{"error": "invalid_grant", "error_description": "..."}
error is one of invalid_request, invalid_grant, invalid_target,
unsupported_grant_type.
HopTokenClaims — the issued JWT's claim set
| Claim | Notes |
|---|---|
iss, sub, aud | Issuer, subject (unchanged across the chain), audience (this hop's target) |
scope, resource | This hop's narrowed data class and target |
exp, iat, jti | Standard; jti is single-use (replay-guarded) |
session_id, policy_version | The pinned session and policy this token was decided against |
hop | Derived depth |
act | Nested delegation proof, or absent at hop 1 |