- A header describing how the token was signed
- A payload containing verified identity attributes
- A signature used to verify freshness and authenticity
Before you start
The agent needs a credential minted to the counterparty’s audience (see Minting Credentials) and the private half of the agent key it was bound to. The counterparty needs nothing from Baselayer directly except the ability to resolve adid:web identifier.The presentation flow
- Discover access requirements. The agent hits the counterparty resource with no credential and is refused
401with aKYA-Disclosure-Scopeheader naming the scope required. It fetchesGET /.well-known/kya-profile.jsonto read the exact fields, purpose, legal basis, and retention for the website or transaction. - Mint on demand. Mint a credential with the required fields (see Minting Credentials).
- Bind to the request. The agent fetches a single-use nonce from the counterparty (
POST /nonces, hosted by the counterparty, not Baselayer) and signs a Key Binding JWT over(audience, nonce), appending it to the credential’s wire string. - Present.
GET /resourcewith theKYA-Credentialheader and the scope reference.
How a counterparty verifies
Before reading a claim, the counterparty verifier:- parses the SD-JWT-VC
- resolves the issuer via
did:web(see “Resolving the issuer’s DID document” below) - verifies the issuer JWT’s signature and expiry
- checks the credential’s live revocation status against its referenced status list (see the Credential Format Reference)
- hashes each disclosure and confirms it is a member of the signed digest set
- verifies the Key Binding JWT against the credential’s bound key, its own audience, and the single-use nonce
- for L2, keys its returning customer record on the pairwise DID
- refuses any disclosure beyond the referenced scope’s fields
DISCLOSURE_DIGEST_MISMATCH; an over-broad presentation fails as SCOPE_VIOLATION. Either failure refuses the whole presentation. A counterparty never keeps the fields it is entitled to and drops the rest.
Resolving the issuer’s DID document
GET /.well-known/did.json — unauthenticated, cacheable for one hour. Every individual and business credential names its issuer as a did:web identifier; resolves it to this document and match the credential’s signing key id (kid, from the JWT header) against verificationMethod. During a key rotation, both the outgoing and incoming key appear here, so a cached document doesn’t reject either.
A counterparty credential is the one exception: its sub resolves through a separate, business-specific document. See the Credential Format Reference.
Implementation recommendations
- Always verify the issuer signature and the Key Binding JWT before reading anything.
- Reject credentials whose
audis not exactly your domain, including your own subdomains and www. variants unless you minted for them. - Cache the registry keys for up to an hour; refresh once on an unknown
kid. - Issue single-use nonces.
- Publish a
kya-profile.jsonand enforce the subset rule. It is what lets you tell a regulator exactly what you can and cannot read. - Treat revoked and expired credentials identically.