Skip to main content

Proof of Possession schema (openid4vci-proof+jwt)

The proof of possession is the JWT a wallet sends in a Credential Request to prove it controls the key a credential will be bound to. Media type openid4vci-proof+jwt, defined in Appendix F.1, jwt Proof Type and Section 8.2 of OpenID4VCI v1.0. It carries the Key Attestation in its header.

JOSE header

FieldStatusMeaning
typREQUIREDMUST be openid4vci-proof+jwt.
algREQUIREDAsymmetric algorithm; none MUST NOT be used.
kidOPTIONALKey ID of the proof key. MUST NOT be present if jwk or x5c is present.
jwk / x5c / trust_chainOPTIONALAlternative ways to carry the proof public key.
key_attestationOPTIONALThe Key Attestation (key-attestation+jwt) attesting the proof key.

Payload claims

ClaimStatusMeaning
issOPTIONALThe Client identifier, when the wallet is a registered client.
audREQUIREDThe Credential Issuer identifier.
iatREQUIREDIssued-at, used for freshness.
nonceconditionalThe c_nonce provided by the Issuer, when one was issued.

OpenID4VCI vs TS3

The proof shape is the same openid4vci-proof+jwt, but the two profiles bind it differently. Switch tabs to compare.

A single proof carrying the KA, signed by one of the attested keys (here k0) with a kid. Header:

{
"typ": "openid4vci-proof+jwt",
"alg": "ES256",
"kid": "k0",
"key_attestation": "eyJ0eXAiOiJrZXktYXR0ZXN0YXRpb24rand0Ii... (the KA)"
}

Payload:

{
"iss": "https://wallet.igrant.io",
"aud": "https://issuer.igrant.io",
"iat": 1780737559,
"nonce": "K3o1c2pZ... (c_nonce)"
}