Skip to main content

EUDI Wallet (eIDAS 2.0)

Beta disclaimer: Mandaitor is currently exploring and implementing EUDI Wallet support, but the required registration and ecosystem onboarding steps are still outstanding. Mandaitor should therefore not yet be described as an official EUDI Wallet party, production Relying Party, or formally recognized participant in the EUDI ecosystem.

The EU Digital Identity Wallet (EUDI Wallet) is the centrepiece of eIDAS 2.0 (Regulation EU 2024/1183). Mandaitor is preparing an integration path to consume verified Person Identification Data (PID) from EUDI Wallets and bind it to mandates once the required registration and operational prerequisites are complete.

Why EUDI Wallet?

eIDAS 2.0 answers "who is this person?" through government-issued PID. Mandaitor answers "may this person act on behalf of another?" through its mandate registry. Together, they provide a complete delegation infrastructure with legally-backed identity verification.

AspectDetails
ProtocolOpenID for Verifiable Presentations (OpenID4VP)
Credential FormatSD-JWT VC (online) + mdoc/ISO 18013-5 (proximity)
Assurance LevelTarget state: HIGH once ecosystem onboarding is complete
PrivacySelective disclosure — only requested attributes shared
DeadlineAll EU Member States must issue wallets by December 2026

Integration Flow

Cross-Device Flow (QR Code)

┌──────────┐ ┌──────────────┐ ┌─────────────┐
│ Dashboard │ │ Mandaitor │ │ EUDI Wallet │
│ (Browser) │ │ API │ │ (Phone) │
└────┬─────┘ └──────┬───────┘ └──────┬──────┘
│ POST /eudi/sessions│ │
│────────────────────>│ │
│ {session_id, qr} │ │
│<────────────────────│ │
│ │ │
│ Render QR Code │ │
│ ┌──────────┐ │ │
│ │ ██ QR ██ │ │ Scan QR │
│ └──────────┘ │<──────────────────────│
│ │ │
│ │ GET /eudi/request/{id} │
│ │<──────────────────────│
│ │ (signed request JWT) │
│ │──────────────────────>│
│ │ │
│ │ User consents │
│ │ │
│ │ POST /eudi/sessions/ │
│ │ {id}/response │
│ │<──────────────────────│
│ │ (VP Token: SD-JWT VC) │
│ │ │
│ Poll GET /eudi/ │ Verify VP Token │
│ sessions/{id} │ ✓ Signature │
│────────────────────>│ ✓ Trusted List │
│ {status: COMPLETED, │ ✓ Revocation │
│ resolved_identity} │ ✓ Nonce │
│<────────────────────│ │

For mobile-first scenarios, Mandaitor returns a deep link (openid4vp://authorize?...) that opens the wallet app directly on the same device.

PID Attributes

The wallet presents Person Identification Data with selective disclosure:

AttributeRequiredDescription
unique_idYesPersistent identifier from the Member State
family_nameYesCurrent surname(s)
given_nameYesCurrent first name(s)
birth_dateOptionalDate of birth (ISO 8601)
nationalityOptionalISO 3166-1 alpha-2 country code

For beta planning and prototype evaluation, Mandaitor currently models three presentation definitions with different data requirements:

  • mandaitor-pid-minimal — Only unique_id (most privacy-preserving)
  • mandaitor-pid-standard — Name + unique ID (default for mandate creation)
  • mandaitor-pid-delegation — PID + delegation EAA attestation

SDK Usage

import { MandaitorClient } from "@mandaitor/sdk";

const client = new MandaitorClient({
apiKey: "mk_live_...",
tenantId: "tnt_your_tenant",
});

// 1. Initiate EUDI session
const session = await client.initiateEudiSession("mandaitor-pid-standard");
console.log(session.qr_code_uri); // Render as QR code
console.log(session.deep_link_uri); // Or open directly on mobile

// 2. Poll for completion (wallet responds asynchronously)
const status = await client.getEudiSessionStatus(session.session_id);
if (status.status === "COMPLETED") {
console.log(status.resolved_identity.subject_id); // "eudi:DE/123..."
console.log(status.resolved_identity.eidas_attributes.family_name);
}

// 3. Create mandate bound to EUDI identity
const mandate = await client.createMandate({
principal: {
type: "NATURAL_PERSON",
subject_id: status.resolved_identity.subject_id,
eidas_attributes: status.resolved_identity.eidas_attributes,
},
delegate: {
type: "AGENT",
subject_id: "agent:my-ai-agent",
},
scope: {
actions: ["construction.validation.approve"],
resources: ["monco:project:*"],
effect: "ALLOW",
},
constraints: {},
eudi_session_id: session.session_id, // Binds the verified identity
});

React Widget

import WalletVerification from "@/components/eudi/WalletVerification";

function MyComponent() {
return (
<WalletVerification
presentationDefinitionId="mandaitor-pid-standard"
onVerified={(session) => {
console.log("Verified:", session.resolved_identity.subject_id);
}}
onError={(error) => console.error(error)}
onCancel={() => console.log("Cancelled")}
/>
);
}

Credential Verification

Once the EUDI integration path is fully enabled, Mandaitor is designed to verify VP Tokens through a multi-step process:

  1. SD-JWT parsing — Decode the compact serialization and extract disclosures
  2. Disclosure hash verification — Verify each disclosure hash matches the _sd array
  3. Cryptographic signature — Verify the JWT signature against the issuer's JWKS
  4. Issuer trust — Check the issuer against the EU Trusted Lists (LOTL)
  5. Credential revocation — Check StatusList2021 / BitstringStatusListEntry status
  6. Nonce validation — Prevent replay attacks with session-bound nonces
  7. Expiration check — Reject expired credentials

mdoc Support

For proximity presentations (BLE/NFC), Mandaitor also supports the mdoc format (ISO 18013-5). mdoc credentials use CBOR encoding and the eu.europa.ec.eudi.pid.1 namespace for PID claims.

Trusted Lists

The intended production integration maintains a cached copy of the EU List of Trusted Lists (LOTL) to verify that PID issuers are legitimate. During beta preparation, this should be understood as target architecture rather than a statement that Mandaitor has already completed every formal onboarding, registration, or recognition requirement of the EUDI ecosystem.