OpenID4VP verifier guide: accepting the EUDI Wallet
How an OpenID4VP verifier works for the EUDI Wallet: request objects, DCQL queries, response modes, SD-JWT VC and mdoc checks, the HAIP rules in EU law, common mistakes and where to test.
By Alberto RosasCo-founder & CEO, DiditUpdated 
In short
OpenID4VP (OpenID for Verifiable Presentations) is the protocol a verifier uses to ask a digital wallet for credentials and get a signed presentation back. Version 1.0 became an OpenID Final Specification on 10 July 2025, and the EU Digital Identity (EUDI) Wallet uses it for remote presentation.[2][3]
- You send a signed request with a DCQL query; the wallet returns a VP Token.
- You verify the issuer signature, disclosures, key binding and revocation yourself.
- For the EUDI Wallet, EU law adds certificate and registration rules.
OpenID4VP is how a website or app asks a wallet to prove something about a person, such as a name or a date of birth. The verifier says which credentials and claims it wants, the user approves in the wallet, and the wallet returns a presentation the verifier checks cryptographically. In the specification's own words, it "defines a protocol for requesting and presenting Credentials".[1]
This guide is for developers building an OpenID4VP verifier for the EUDI Wallet: the request object, DCQL, response modes, device flows, SD-JWT VC and mdoc checks, the HAIP rules in EU law, common mistakes and where to test.
OpenID4VP in plain words
OpenID4VP reuses the shape of an OAuth 2.0 authorization request. The verifier asks for the response type vp_token, and a successful response must include a vp_token parameter carrying the presentations.[1] There is no code or access token to exchange: the data arrives in the response.
The wallet authenticates the relying party, checks it asks for no more than it registered, collects the user's approval and signs the presentation. The relying party then verifies the issuer signature, the revocation status and the device binding.[3] The person identification data (PID) is issued in two formats, SD-JWT VC and ISO/IEC mdoc, and both use salted hashes so the user can share some attributes and hide the rest.[5][3]
- 10 July 2025Final specOpenID4VP 1.0 approved.
- 22 July 2026PublishedCIR 2026/1731 (adopted 15 July 2026) in the Official Journal.
- 23 July 2026ARF v3.0.0Current architecture release.
- 24 December 2026WalletsAt least one per Member State.
- 24 December 2027AcceptanceRegulated private relying parties.
From final specification to the private-sector acceptance date.[2][3][4][5]
How an OpenID4VP verifier exchange works
OpenID4VP publishes a reference design for the response mode direct_post, where the wallet posts the response to a server endpoint instead of sending it through the browser.[1]
Wallet checks the verifier, user consents
The direct_post reference design in OpenID4VP 1.0, section 13.3, simplified.[1]
- Generate a nonce of "at least 16 fresh, cryptographically random bytes" per request.
- Send the request-id from the response endpoint to the wallet as
state. - Return a redirect URI with a fresh
response_codeonce the wallet posts. - Fetch the VP Token with the transaction-id and that code, then check the nonce.
The response_code blocks session fixation, where an attacker relays your request to a victim's wallet. The specification notes it does not help across devices and recommends extra mechanisms there.[1]
An OpenID4VP presentation from an EUDI Wallet, start to finish.
The OpenID4VP request object and client identifiers
The client_id starts with a Client Identifier Prefix that tells the wallet how to authenticate the verifier.[1] Large requests travel by reference: the wallet fetches the signed request object from a request_uri. For QR codes, the specification recommends direct_post with request_uri, since the request "might not fit in a QR code".[1]
| Prefix | How the wallet authenticates the verifier | Signed request |
|---|---|---|
redirect_uri | The identifier is the redirect or response URI | Cannot be signed |
x509_san_dns | DNS name in the leaf certificate's SAN | Required |
x509_hash | SHA-256 hash of the leaf certificate | Required |
decentralized_identifier | Key from the DID Document | Required |
verifier_attestation | Attestation JWT from an issuer the wallet trusts | Required |
openid_federation | Federation trust chain | Per OpenID Federation |
Client Identifier Prefixes, OpenID4VP 1.0 section 5.9.[1]
For EUDI verifiers, EU law picks the prefix: the leaf certificate "for use with the x509_hash Client Identifier Prefix shall be a RP access certificate as specified in ETSI TS 119 475", and one element of verifier_info "shall include the registration certificate".[5]
DCQL queries: ask for what you registered
The Digital Credentials Query Language (DCQL) is the JSON query that names the credentials and claims you want. It holds a required credentials array and an optional credential_sets array; each credential query needs an id, a format and a meta object.[1] The specification's SD-JWT VC example:[1]
{ "credentials": [ { "id": "my_credential", "format": "dc+sd-jwt", "meta": { "vct_values": [ "https://credentials.example.com/identity_credential" ] }, "claims": [ {"path": ["last_name"]}, {"path": ["first_name"]}, {"path": ["address", "street_address"]} ] } ] }
For an mdoc, the format is mso_mdoc and meta carries a doctype_value.[1] For the PID, swap in its type and claim names; the mandatory PID attributes are family name, given name, birth date, birth place and nationality.[7]
require_cryptographic_holder_bindingdefaults to true. Keep it: it makes the wallet return a key binding proof.[1]trusted_authoritiesonly filters what the wallet offers. Verifiers "must verify that the issuer of a received presentation is trusted on their own".[1]- Relying parties "shall not request users to provide any data other than" what they registered, and the wallet checks.[4][3]
OpenID4VP response modes
The response mode decides how the VP Token travels back. The default for vp_token is fragment, in the fragment of the redirect URI.[1]
| Response mode | Where the VP Token goes | Encrypted |
|---|---|---|
fragment | Redirect URI fragment, through the browser | No |
direct_post | HTTP POST to the response_uri | No |
direct_post.jwt | HTTP POST of an encrypted JWT | Yes |
dc_api | Back through the Digital Credentials API | No |
dc_api.jwt | Same, encrypted | Yes |
Response modes in OpenID4VP 1.0.[1]
With direct_post, response_uri is required and redirect_uri must be absent, or the wallet returns invalid_request.[1] Moldova's EVO Wallet, for example, documents OpenID4VP 1.0 with direct_post.jwt in a same-device flow, ISO/IEC 18013-5 mdoc profiled per OpenID4VC HAIP 1.0, and an IETF Token Status List for revocation.[11]
Same-device, cross-device and the Digital Credentials API
The ARF lists the supported remote combinations: OpenID4VP combined with a transmission mechanism based on redirects and custom URI schemes; OpenID4VP or ISO/IEC 18013-7 combined with the W3C Digital Credentials API; and, optionally, ISO/IEC 18013-7 with redirects and custom URI schemes.[3]
Same device
Custom URI scheme
- The browser hands openid4vp:// to the operating system
- The wallet opens on the same phone
ARF 4.4.3.1
Cross device
QR code
- The desktop shows a QR code to scan
- Open to phishing and relay
ARF 4.4.3.1
Browser API
Digital Credentials API
- The browser passes the verified origin
- Enabled by default in Chrome 141
OpenID4VP Appendix A
Three ways a wallet receives an OpenID4VP request.[3][1][10]
The ARF says custom URI schemes are "not recommended for cross-device flows" and names the Digital Credentials API as the alternative.[3] Over the API, the wallet learns the verifier's origin as authenticated by the browser, "which is important for phishing resistance".[1] The W3C specification is still a draft.[9] What the user sees on a phone:
Verify your identity
This website asks your wallet for your details.
1The browser sends an openid4vp:// URI to the operating system.[3]
Checking the request
The wallet opens and connects to the relying party.
2The wallet authenticates the relying party and checks what it registered.[3]
Choose what to share
- Family nameShared
- Birth dateShared
- AddressNot shared
Share
3The user approves the attributes.[3]
Details received
4The wallet posts and returns the user.[1]
Verifying an SD-JWT VC presentation step by step
An SD-JWT VC presentation carries the issuer-signed JWT, the disclosures the user revealed and a Key Binding JWT. The verifier "MUST validate every individual Verifiable Presentation" and reject any with the wrong nonce.[1]
1Verify the issuer signature
The key chains to a trusted PID or attestation provider.
2Check every disclosure
Each one hashes to a digest in the signed payload.
3Verify the Key Binding JWT
Holder key signature; nonce and audience match.
4Check revocation
Read the issuer's status list.
Every check passes
Use the disclosed attributes
Reject and offer another route
The verifier's checks on one SD-JWT VC presentation.[1][3]
Issuer signature. The ARF lists it first among the relying party's checks. Trust anchors come from Trusted Lists (ETSI TS 119 612) and Lists of Trusted Entities (ETSI TS 119 602).[3]
Disclosures. The signed payload holds an _sd array of digests; each disclosure is a salt, a claim name and a value, such as ["eluV5Og3gSNII8EYnsxA_A", "family_name", "Doe"].[1] Hash each one and find its digest. No match means the issuer did not sign it.
Key Binding JWT. When holder binding is required, the wallet "MUST return an SD-JWT with a Key Binding JWT". Its nonce must equal your request's nonce and its aud your Client Identifier, or over the Digital Credentials API your origin prefixed with origin:.[1] The specification's example:
{ "nonce": "n-0S6_WzA2Mj", "aud": "x509_san_dns:client.example.org", "iat": 1709838604, "sd_hash": "Dy-RYwZfaaoC3inJbLslgPvMp09bH-clYP_3qbRqtW4" }
Revocation. The relying party verifies the provider "did not revoke the PID or attestation".[3] Moldova's EVO Wallet, for one, documents an IETF Token Status List for this.[11]
Note
The PID portrait becomes mandatory only from 11 August 2028, so do not plan a face match against the wallet portrait before then.[5]
mdoc presentations via ISO/IEC 18013-7, in brief
For an mdoc, the VP Token holds a base64url-encoded DeviceResponse from ISO/IEC 18013-5 that "contains a signature or MAC over the SessionTranscript", including an OpenID4VP handover structure.[1] That handover binds the mdoc to your request, the way nonce and audience bind an SD-JWT VC.
Watch out
EU law applies "Annex C to ISO/IEC 18013-7:2025" for mdoc over the Digital Credentials API.[5] ISO lists the 2024 edition of 18013-7 as withdrawn and replaced, so check which edition your library implements.[8]
Our SD-JWT VC vs mdoc comparison covers when each format fits.
What the HAIP profile adds for EUDI verifiers
The High Assurance Interoperability Profile (HAIP) narrows OpenID4VP's options. The ARF already requires it for issuance, saying its use "is necessary to ensure interoperability".[3] For presentation, CIR 2026/1731 sets an "OpenID4VC-HAIP profile" and an "ISO/IEC-mdoc profile".[5]
| Requirement | For your verifier | Source |
|---|---|---|
| Access certificate | Sign with an x509_hash RP access certificate, ETSI TS 119 475 | CIR 2026/1731[5] |
| Registration certificate | Include it in verifier_info | CIR 2026/1731[5] |
| Registration | Register where you are established | eIDAS Art. 5b(1)[4] |
| Wallet checks | Wallet units validate registration certificates only from 11 August 2028; not a registration deadline | CIR 2026/1731[5] |
The registration certificate "describes the intended use of the relying party and indicates the attributes" it registered, and the registration regulation applies from 24 December 2026.[6] The 11 August 2028 date only covers the wallet-side check of that certificate, not registration.[5] Germany sums it up: an organisation "receives an access and registration certificate for the organization and the use case".[12] Our EUDI Wallet relying party guide covers registration in full.
Common mistakes when building an OpenID4VP verifier
| Mistake | Fix |
|---|---|
| Reused or short nonces | At least 16 fresh random bytes per request[1] |
| No audience check | Compare aud with your Client Identifier or origin[1] |
| Asking for unregistered data | Build the DCQL query from your registration[4] |
| Custom URI QR codes across devices | Prefer the Digital Credentials API[3] |
Trusting trusted_authorities | Validate the issuer against trust lists yourself[1] |
| Skipping revocation | Check the status every time[3] |
Signing with the redirect_uri prefix | It cannot be signed; use x509_hash[1][5] |
The wallet is also voluntary: access "shall not in any way be restricted or made disadvantageous" for people who do not use it, so your verifier sits next to another route.[4]
Testing resources
Start with reference software and conformance tests before you test against national wallets.
- Run the conformance tests at conformance.eudi.dev.[3]
- Read the reference implementation docs at docs.eudi.dev, which are documentation, not tests.[3]
- Study the National Bank of Moldova's demo verifier and its source code.[13]
- Check the Digital Credentials API draft before relying on the browser route.[9]
For the dates behind your test plan, see EUDI Wallet deadlines for 2026 and 2027.
How Didit helps with EUDI Wallet verification
EUDI Wallet acceptance is coming soon on Didit: it is on our roadmap, aligned with the EUDI Wallet timeline, in the same workflow you use today. Meanwhile, you can verify people remotely now.
- Five national eIDs run in Didit today through eID verification: MitID, BankID Sweden, Finnish Trust Network, Smart-ID and Mobile-ID. See eID verification.
- If a person has no eID, the flow falls back to document verification with NFC chip reading, liveness and face match, configured per country. A full KYC check costs $0.33.
- AML screening runs in the same flow at $0.20.
You keep your relying-party duties. The eID integrations docs show how eIDs are turned on per country.
Didit provides
- National eID sign-ins and the document route in one workflow
- The evidence of every check
Stays with you
- Your wallet-relying party registration
- The onboarding decision and your policies
Plan your EUDI Wallet route with us
Tell us your countries and use case, and start with national eIDs and documents today.
Key takeaways
- OpenID4VP 1.0 is a final OpenID specification since 10 July 2025.
- Send a DCQL query capped by your registration and a fresh nonce.
- Verify the issuer signature, every disclosure, the Key Binding JWT and revocation.
- EUDI verifiers sign with an
x509_hashRP access certificate. - Private relying parties in scope accept the wallet by 24 December 2027.
Frequently asked questions
What is OpenID4VP?
OpenID for Verifiable Presentations is a protocol for requesting and presenting credentials. The wallet returns signed presentations in a VP Token, with no authorization code or access token to exchange. Version 1.0 became an OpenID Final Specification on 10 July 2025.[1][2]
Does the EUDI Wallet use OpenID4VP?
Yes, for remote presentation, next to ISO/IEC 18013-7. EU law sets an OpenID4VC-HAIP profile and an ISO/IEC-mdoc profile.[3][5]
What is DCQL?
The Digital Credentials Query Language is the JSON query naming the credentials and claims a verifier wants. The wallet returns presentations that match. For the EUDI Wallet, ask only for the attributes you registered.[1][4]
Which response mode should an EUDI verifier use?
A server-side verifier uses direct_post or the encrypted direct_post.jwt. Over the Digital Credentials API, the modes are dc_api and dc_api.jwt.[1]
How do I verify the Key Binding JWT?
Check its signature with the key bound in the credential, then check its nonce and audience against your request. Over the Digital Credentials API, the audience is your origin.[1]
Which client identifier prefix do EUDI verifiers use?
x509_hash, with an RP access certificate per ETSI TS 119 475. The registration certificate goes in verifier_info.[5]
Can I use a QR code across devices?
You can, but the ARF does not recommend custom URI schemes across devices because of phishing and relay attacks. It names the Digital Credentials API as the alternative.[3]
Can I face-match against the wallet portrait?
Not reliably yet. The portrait becomes mandatory PID data only from 11 August 2028.[5]
Where can I test an OpenID4VP verifier?
Run the conformance tests at conformance.eudi.dev and read the reference implementation docs at docs.eudi.dev. Moldova's central bank also published a demo verifier with source code.[3][13]
Sources
- OpenID for Verifiable Presentations 1.0, OpenID Foundation, Final Specification.
- OpenID for Verifiable Presentations 1.0 Final Specification Approved, OpenID Foundation, 10 July 2025.
- Architecture and Reference Framework v3.0.0, eu-digital-identity-wallet on GitHub, release of 23 July 2026.
- Regulation (EU) 2024/1183 (eIDAS 2), EUR-Lex, Official Journal of 30 April 2024.
- Commission Implementing Regulation (EU) 2026/1731, EUR-Lex, Official Journal of 22 July 2026.
- Commission Implementing Regulation (EU) 2025/848 on the registration of wallet-relying parties, EUR-Lex, Official Journal of 7 May 2025.
- Commission Implementing Regulation (EU) 2024/2977 on person identification data, EUR-Lex, Official Journal of 4 December 2024.
- ISO/IEC 18013-7, ISO standard page.
- Digital Credentials, W3C draft.
- Digital Credentials API shipped, Chrome for Developers.
- EVO Wallet developer guide, Government of Moldova, egov4dev.
- EUDI Wallet FAQ, eudi-wallet.gov.de.
- BNM demo verifier, Government of Moldova, egov4dev.
OpenID4VP is the part of the EUDI Wallet developers touch most, and it is stable enough to build against. See how Didit approaches wallet acceptance on the EUDI Wallet solution page, and the wider picture in our eIDAS 2 overview.
Verify people remotely while wallets roll out
Use national eIDs and the document route now, and talk to us about the EUDI Wallet.
Related articles
- Didit vs Unit21: KYC, KYB, AML and monitoring on one record
- Didit vs Trinsic: eID sign-in plus document checks, AML and KYB
- Didit vs Thomson Reuters: government databases plus the whole flow
- Didit vs Regula: hosted checks with full evidence, KYB and monitoring
- Top 10 AI compliance agents for KYC and AML review automation in 2026
- Top 5 Travel Rule compliance solutions for crypto businesses in 2026