With Regulation (EU) 2024/1183 the European Union has put in place a framework that obliges every member state to issue a digital wallet to its citizens — and obliges large parts of the economy to accept it. A five-page overview of what this changes for architects in regulated industries: the trust triangle, the two mandatory credential formats, and a concrete OID4VP sequence that lets a bank run KYC without a video-identification call.
Context — a regulation with a deadline
The original 2014 eIDAS regulation set up a common EU framework for trust services — qualified signatures, seals, time-stamps, the notification of national eID schemes. It was a technically clean piece of work, but largely invisible in the private sector: banks, telcos and energy providers ignored notified eIDs at scale, and Germany's online-enabled identity card never reached the mass market in twelve years on the street. eIDAS 2.0 — formally Regulation (EU) 2024/1183 of 11 April 2024 — addresses this gap at two points: it obliges every member state to provide a EUDI Wallet (European Digital Identity Wallet), and it obliges a clearly defined set of verifiers to accept it.
The central deadline is on the table: 20 November 2026. By that date every member state must have at least one certified wallet in the market. The associated implementing acts — most notably Commission Implementing Regulation 2024/2982 on protocols, interfaces and certification — were adopted in late 2024; several CIRs on trust services and cross-border identity matching followed in 2025. Realistically the deadline will not hold uniformly across all 27 member states — Italy and Spain are running early, Germany and France are negotiating a grace period. For an application architecture that has to last two or three years, this is a side question: by the end of 2027 the wallet will be in production in Germany under any plausible scenario.
The commercially relevant part is the list of verifiers under acceptance duty. Article 5f names them explicitly: public administration, banks and other entities subject to anti-money-laundering obligations under 6AMLD, telecommunications providers, energy and utility providers, the transport sector, education, healthcare, postal services and the very large online platforms under the Digital Services Act (VLOPs — Amazon, app stores, social networks). Anyone on that list cannot ignore the wallet in 2027; anyone advising a client in one of those sectors needs the wallet-verifier integration on their roadmap. The common objection "we will implement this later, once the wallet is established in the market" misses the point — the acceptance duty is statutory, not market-driven.
A second novelty is the introduction of the Electronic Attestation of Attributes as a separate trust-service category. eIDAS 1 knew qualified signatures and seals; eIDAS 2 adds three sub-classes of attribute-based attestations: Personal Identification Data (PID, the state-verified base identity), Qualified Electronic Attestation of Attributes (QEAA, issued by a qualified trust service) and Public-Sector EAA (PuB-EAA, issued by an authority). This extends the concept of a qualified trust service from signatures to the issuance of facts — a university that issues a diploma into the wallet becomes a potential QEAA provider with the same legal binding force as a qualified certificate service.
Two further aspects are politically baked in and technically non-trivial. First, the regulation mandates wallet components as open source where security considerations do not stand in the way — the EU reference implementations on GitHub under eu-digital-identity-wallet are not a friendly gesture from the Commission but a regulatory obligation. Second, Article 5a(16) explicitly requires the wallet to support zero-knowledge proofs and minimum disclosure. What that means in practice — and why it can only be partially delivered in 2026 — gets concrete in the section on credential formats.
Trust triangle — holder, issuer, verifier
The EUDI Wallet builds on a familiar architecture pattern: three roles, three cryptographic bindings, one trust anchor per member state.
The holder is the natural person and the wallet instance operated on their behalf, in most cases an app on the citizen's smartphone. It manages credentials and their key material — the latter does not live in normal app storage but in a Wallet Secure Cryptographic Device (WSCD), in practice the smartphone's secure element, the eSIM, or an external smart card. The compliant implementation separates a software-side Wallet Secure Cryptographic Application (WSCA) from the underlying WSCD; for everyday purposes it is enough to know that the private key never leaves the hardware element.
The issuer issues credentials. The regulation distinguishes three sub-classes: PID providers (in Germany most likely Bundesdruckerei, with the national ID card's eID function as the anchor), QEAA providers (qualified trust services supervised by the national regulator) and non-qualified EAA providers (anyone who wants to attest an attribute — a university for a diploma, an employer for an employment certificate, a utility for a contract anchor). The qualified variant carries higher requirements on applicant identification, operational security and supervisory reporting, in exchange for stronger legal binding force.
The verifier — the relying party — is the requesting entity, for example the bank in an account-opening flow or the police device in a mobile-driving-licence check. Unlike eIDAS 1, where anyone could consume eIDs ad libitum, a verifier registration is now mandatory: every verifier is entered into a national relying party registry before going live, with declared purposes and the specific attributes it is allowed to request. The wallet consults this registry on the authorization request and refuses queries that go beyond the registration. This is the central safeguard against the over-asking incentive that hits any verifier system without a cap on requested attributes.
The trust anchor is the EU List of Trusted Lists (LOTL), already familiar from eIDAS 1 and now extended by four new lists: wallet providers, PID providers, QEAA/PuB-EAA providers and the relying party registries. Each member state publishes its list signed; the LOTL aggregates them. A wallet notified in Spain can be validated in Germany because its issuer certificate is in the Spanish wallet-provider list — and the wallet software on the device carries a Wallet Trust Mark that attests the authenticity of the wallet instance itself to the verifier.
Credential formats — SD-JWT VC and mDoc
The Architecture Reference Framework mandates two formats that every wallet and every verifier must support in parallel. If you are building a verifier component, you cannot avoid either.
SD-JWT VC (Selective Disclosure JWT for Verifiable Credentials, IETF draft draft-ietf-oauth-sd-jwt-vc) is the JOSE-rooted path. A credential is a JWT signed by the issuer in which sensitive claims are not stored in clear text but as hashes. The corresponding clear-text values (called disclosures) sit separately — Base64URL-encoded triples of salt, claim name and claim value. When presenting to a verifier the wallet attaches only the disclosures it wants to reveal; the others stay as hashes in the JWT, proving their existence without revealing their content. A key-binding JWT at the end of the chain signs the selection with the holder key against verifier audience and nonce. Wire format: <jwt>~<disclosure1>~<disclosure2>~...~<kb-jwt>. The vct claim in the JWT header declares the credential type, typically a URL like urn:eu.europa.ec.eudi:pid:1.
mDoc is the ISO-rooted path: ISO/IEC 18013-5 originally as mobile driving licence, extended in 18013-7 to online presentation over OID4VP. Unlike SD-JWT VC, mDoc is CBOR-encoded and signed with COSE_Sign1 — more compact, but less developer-friendly because JOSE tooling does not transfer cleanly. The structure is hierarchical, organised by namespaces: org.iso.18013.5.1 for mDL fields, eu.europa.ec.eudi.pid.1 for the EU PID. The MobileSecurityObject carries the issuer signature and the hashes of items per namespace; on presentation only disclosed items are sent, and hash comparison proves integrity without revealing the value.
Which format where? For the DACH market and for education use cases SD-JWT VC dominates, because the tooling ecosystem (JOSE libraries, OIDC experience) is more accessible. For mobile driving licences and anything touching the automotive and law-enforcement transport space, mDoc is given — police roadside readers are certified against ISO 18013-5, that is not going to be replaced by SD-JWT. A production verifier component supports both; that is extra work but unavoidable.
Selective disclosure is technically clean in both formats — minimum disclosure such as the boolean age_over_18 without a date of birth works with standard tooling. It gets harder with the unlinkability the regulation demands: two presentations of the same credential at two different verifiers should not be linkable, not even by collusion between verifier and issuer. Plain ECDSA signatures do not achieve that — the issuer signature is identical across both presentations and ties them together. Today's best practice is batch issuance: the issuer issues not one credential but fifty or a hundred, and the wallet uses a different one per verifier. That shifts the problem (the issuer still knows the holder identity, but the verifier-to-verifier link is broken) at the cost of issuance resources. The mathematically clean answer would be BBS+ signatures, which support selective disclosure with unlinkable re-randomisation from a single issuer signature — they are named as a target state in ARF 2.x but not deliverable in 2026 because no available secure element can sign BBS+ in hardware.
Revocation is the third technical knot. The EU wallet uses the IETF Token Status List (draft-ietf-oauth-status-list) — a zlib-compressed bit string where each bit encodes one credential's status (valid, revoked, suspended). Verifiers fetch the list periodically, cache it locally and check the bit at the index named in the credential. That is efficient, but it has the side effect that the status list is queried by the issuer at fine granularity — if you are not careful you build yourself an OCSP equivalent with the same profiling risks.
OID4VCI — how a credential gets into the wallet
OpenID for Verifiable Credential Issuance is the spec that describes the path from issuer to wallet. It is final at 1.0 and underpins the EUDI implementation.
Issuer metadata is published at /.well-known/openid-credential-issuer. The credential_configurations_supported block declares, per offered credential type, the format (vc+sd-jwt or mso_mdoc), the vct or doctype, the supported claims, the cryptographic binding methods and the accepted proof types. Wallets read this metadata first, before they begin any authorization request.
Two flows are central. The pre-authorized code flow is the standard variant for scenarios where the holder is already authenticated in the issuer context — the student logged into the university portal, the authority that has already identified the citizen in an administrative procedure. The issuer builds a credential offer with a single-use pre-authorized_code and an optional tx_code (a short PIN the holder additionally enters) and delivers it to the wallet as a QR code or deep link openid-credential-offer://?.... The wallet exchanges the code at the token_endpoint for an access token, builds a proof JWT with the holder key against the c_nonce supplied by the issuer, calls credential_endpoint and receives the credential. A notification endpoint confirms successful storage.
The authorization code flow is used when the issuer needs to authenticate the holder at issuance time — that is true in particular for initial PID issuance, where an eID read of the identity card is part of the flow. The wallet starts a classic OAuth flow with PKCE against the issuer authorization server, goes through eID authentication, receives an authorization code, exchanges it for an access token and then fetches the credential. The EU reference PID issuer (eudi-srv-pid-issuer on GitHub) implements this flow exclusively — pre-authorized is not allowed for PID.
OID4VP — how a credential gets presented out of the wallet
OpenID for Verifiable Presentations is the spec for the reverse direction: a verifier requests a presentation, the wallet presents selectively, the verifier validates. This is the technical heart of every application that consumes EUDI wallets.
The verifier starts by building a signed authorization request object — a JWT declaring the client under client_id (usually an X.509 identity with a DNS SAN), setting the response_mode, putting the nonce in place, embedding the presentation_definition (DIF Presentation Exchange) or the more compact dcql_query (Digital Credentials Query Language) and naming the endpoint at response_uri to which the wallet later POSTs its response. Rather than handing the request object over inline, the verifier deposits it at a URL and only passes the request_uri to the wallet — necessary because the whole JWT would not fit into a QR code.
The response_mode controls security and platform properties. direct_post is the default for cross-device flows: the wallet POSTs the response as an HTTPS form to the verifier endpoint. direct_post.jwt additionally encrypts that response as a JWE — relevant where the browser showing the QR code might be compromised. dc_api or dc_api.jwt uses the browser Digital Credentials API (W3C WICG): a JavaScript call navigator.credentials.get({digital: {...}}) returns the vp_token to the calling page, without a custom-scheme round trip and without a separate HTTPS endpoint. Same-device flows in the browser will converge on this mechanism in the medium term; Chrome has supported it as a default since mid-2025, Safari and Firefox are following.
The same-device flow on a smartphone runs over custom-scheme deep links: a click on openid4vp://?client_id=...&request_uri=... opens the wallet app. The cross-device flow — desktop browser plus wallet on the phone — uses QR codes with the same URL structure. Phishing protection is essential here: the wallet validates the cert chain of the request object against the member state's trusted lists and accepts only response_uri values consistent with the client_id certificate.
Sequence — bank KYC without VideoIdent
A concrete example shows best what a EUDI Wallet integration actually does. Scenario: a German bank opens an account online and replaces the existing video-identification process with an OID4VP integration to the wallet.
Cross-device OID4VP flow for an account opening. Dashed arrows are response paths. Step 5 (holder consent) happens locally in the wallet — the holder sees the requested fields and explicitly approves what gets disclosed.
What the bank actually requests sits in the presentation_definition or dcql_query: for KYC typically given_name, family_name, birthdate, nationality, place_of_birth and address, plus a PEP indication where relevant. If only age verification is needed for an online tobacco shop, the request collapses to the boolean age_over_18 — name and date of birth stay in the wallet. That is the regulatory demand in its purest form. BaFin signalled in the 2025 consultation that a EUDI Wallet identification at level of assurance high is recognised as equivalent to the existing video-identification under § 12 GwG — the commercial lever is significant, because the manual review step in VideoIdent goes away and only automated signature and trust-anchor validations remain.
Libraries and reference implementations
The European Commission and several open-source initiatives publish enough mature code that a verifier or issuer component does not need to be built from zero.
The EU Reference Implementation at github.com/eu-digital-identity-wallet covers a verifier (Spring Boot Kotlin, eudi-srv-web-verifier-endpoint-23220-4-kt), a PID issuer, mobile wallet clients for Android and iOS and the Architecture Reference Framework documentation. The verifier is a reasonable starting point for a JVM-based application — it covers OID4VP with DCQL and Presentation Exchange, supports direct_post and direct_post.jwt and is conformance-tested against the EUDIW spec.
In the JVM world walt.id (github.com/walt-id/waltid-identity) offers a Kotlin Multiplatform stack covering issuer, verifier and wallet — OID4VCI, OID4VP, SD-JWT, mDoc, W3C VC under one codebase. In TypeScript the choice is Sphereon OID4VC for a modular stack and Credo-TS (Open Wallet Foundation) for a multi-protocol platform combining OID4VC and DIDComm. eudiplo, from the same foundation, positions itself as HTTP middleware: you put a small REST API between backend and wallet rather than carrying OID4VC complexity inside the application — useful when the business logic is not written in the same language as the wallet library.
For mobile, Multipaz (Kotlin Multiplatform, also Open Wallet Foundation) is the choice for ISO-18013-centric use cases with Bluetooth proximity flows; Lissi ships SDKs for the DACH context that play a leading role in the German wallet initiative.
Pitfalls — what goes wrong early
The spec landscape is consolidated, but implementations are young. Three classes of problems recur in pilot projects.
Wallet heterogeneity. Every member state notifies its own wallets, and all are supposed to interoperate. In practice differences show up in disclosure ordering, optional fields, crypto suites and the handling of edge cases. The High Assurance Interoperability Profile (HAIP) reduces variability significantly — anyone building a verifier should develop against HAIP, not against the OID4VP spec in general. Even so, end-to-end testing against at least the DE, IT, FR and ES wallets is mandatory before a production rollout.
Phishing via response_uri. An attacker impersonating a verifier domain can craft an OID4VP request carrying the correct client_id of a real bank and direct response_uri at their own server. The wallet therefore has to check that the client_id appears in the cert chain of the request object and that response_uri sits under the same effective top-level domain. HAIP makes signed request objects mandatory; inline plain authorization requests are no longer permitted. If you build the wallet integration yourself, that validation should be the first test in your pipeline.
Schema versioning on vct. If the PID issuer introduces an extra mandatory claim in 2028, that breaks verifiers validating against the older version. Best practice: keep a version suffix in the vct URL (urn:eu.europa.ec.eudi:pid:1 versus :pid:2) and define a version tolerance window in the verifier. ARF 2.x defines the conventions, but they are not yet fully settled.
Status-list caching. A naive implementation fetches the status list fresh on every presentation — that overloads the issuer endpoint and makes verifier latency unworkable. A production implementation caches the list locally (typically minutes to hours, depending on issuer update frequency) and accepts the small gap between revocation and cache refresh. If you demand real-time revocation here, you build yourself an OCSP equivalent with all its scaling problems.
Recommendation
If you run an application in an acceptance-bound sector — bank, insurer, energy provider, telco, large online platform — 2026 is not the year to wait. The order that has worked for us in projects: first build the OID4VP verifier component as an isolated module and test against the EU reference wallet and one of the DACH wallets (Lissi demo, Animo Paradym). Second, integrate the verifier into the existing identity stack — the wallet is an additional authentication source alongside today's stack, not a replacement. Third, add trust-anchor fetching, status-list caching and HAIP conformance as a hardening layer.
What makes the EUDI Wallet attractive for regulated industries is the removal of the manual identification step. VideoIdent is expensive, customer-hostile and painful to scale. Wallet-based identification reduces the step to a cryptographic signature check — once the stack is in place, the marginal cost per identification is close to zero. That investment has to happen now, in the phase where the wallet is not yet at mass adoption — anyone waiting for the queue to form will find no counter staff ready when it does.
EUDI Wallet verifier or KYC modernisation?
We integrate OID4VP verifiers into Spring Boot and Node applications, translate the Architecture Reference Framework into a workable architecture for regulated industries and run conformance testing against the EU reference wallet. The result: a reliable integration ready for the deadline — and a migration path away from manual identification.