Skip to main content

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