Binding
Three distinct "binding" guarantees run through OpenID4VP, each closing off a different class of attack. Getting all three right is what separates "the wallet showed a valid credential" from "the wallet showed a valid credential, bound to this holder, for this session, for this exact transaction" — the actual security property you need.
Holder Binding
Holder binding proves that the entity presenting the credential is the same entity to whom it was issued. The
wallet holds a private key tied to the credential (via the cnf claim in SD-JWT-VC, or DeviceKey in mdoc) and
produces a proof-of-possession signature over the presentation. Your response validation must verify this signature
against the bound public key — verifying only the issuer's signature on the credential is not enough.
Session Binding
Session binding ties the presentation to this specific OpenID4VP exchange, not just to the holder in the
abstract. It is enforced through the nonce you generate per request and require the wallet to echo inside its
cryptographic proof — this is what stops a genuine presentation from being captured and replayed against a different
verifier or a later session.
Transaction Binding
Transaction binding (via the transaction_data parameter) cryptographically ties the presentation to the specific
business transaction the user consented to — e.g. "I consent to share my age to complete this exact €50 payment." The
wallet signs a hash of the transaction data alongside the credential proof, so your backend can detect a presentation
being reused for a transaction the user never actually saw or approved.
Further Reading
Key topics: cnf claim / key-binding JWT (SD-JWT-VC), DeviceSigned structure (mdoc), nonce-based replay protection,
transaction_data parameter, proof-of-possession validation.
OpenID4VP — Terminology (Holder Binding / Key Binding) · OpenID4VP — Transaction Data