EU ID Wallet Software · Malta · Ecosystem integrations

Build for the European Digital Identity Wallet with CodeB.

EU ID Wallet software, built in Malta by Aloaha Limited. Whether you are a Relying Party asking for a presentation, a public authority issuing credentials, a wallet vendor publishing your Wallet Attestation trust anchors, or an operator running a national trust list — the endpoints, snippets, and drop-in scripts below hook straight into the European Digital Identity Wallet ecosystem. Self-hostable, sovereign, Malta-registered. The upstream reference is docs.eudi.dev; nothing on this page is endorsed by the European Commission.

Honest scope. CodeB ships OID4VP FINAL, OID4VCI 1.0 Final, SD-JWT VC, mso_mdoc, and HAIP section 5.11 Wallet Attestation today.

Pick your role

Verifier / Relying Party

Ask for a presentation from a holder's wallet. Poll for completion, read claims.

Issuer

Mint SD-JWT VC or mso_mdoc credentials for holders via OID4VCI credential offers.

Wallet provider

Publish Wallet Attestation JWKS / PEM so verifiers can enforce HAIP §5.11.

Trust-anchor operator

Supply LOTL, SD-JWT-VC issuer, or mDoc issuer certificates to the verifier trust store.

Verifier setup

Every verifier flow uses the same three moves against the CodeB tenant: vp-start to open a presentation session, render the returned deep link (QR or native invocation), then poll vp-status until the wallet completes it.

1. Open a session

POST /oidc.ashx?action=vp-start&query=<NAME> Response 200 application/json: { "id": "vps_...", "request_uri": "https://<CODEB_TENANT_HOST>/oidc.ashx?action=vp-request&id=vps_...", "deep_link": "openid4vp://?client_id=<VERIFIER_ID>&request_uri=..." }

2. Render the deep link

Convert deep_link to a QR code for desktop flows, or invoke it directly on mobile. The deep link uses the openid4vp:// scheme (or haip:// when the tenant is configured for HAIP).

3. Poll for completion

POST /oidc.ashx?action=vp-status&id=<id> Response 200 application/json: { "status": "waiting" | "completed" | "expired" | "error", "claims": { "sub":"...", "given_name":"...", "eudi_verified": true, ... } }

4. Copy-paste JS

The vanilla-JS snippet handles the render + poll cycle. It exports one function:

CodeBVerifier.startSignIn({ query: "pid-minimal", mount: document.getElementById("qr"), onDone: function (claims) { /* your handler */ } });

A React hook variant lives at verifier-react-hook.jsx. Framework-scoped wrappers for Vue and Angular ship on the verifier integration cookbook.

Issuer setup

The issuer flow follows OID4VCI 1.0 Final (dedicated Nonce Endpoint, Notification Endpoint, credentials[] response shape; the Draft-15 scalar credential field is preserved as a backward-compat fallback). You declare which credential types your tenant supports, mint a credential offer per holder, and hand the wallet a openid-credential-offer:// deep link.

1. Declare supported VCTs

Drop VCT metadata JSON files under App_Data/<tenant>/vci/, or use the vci-admin UI. Each VCT declares its credential format (vc+sd-jwt or mso_mdoc), claims, and cryptographic constraints.

2. Mint a credential offer

POST /vci.ashx?action=credential-offer Body: { "credential_configuration_ids": ["codeb-org-employee-sd-jwt-vc"], "holder_hint": { "email": "alice@example.com" } } Response 200: { "credential_offer_uri": "https://.../vci.ashx?action=offer&id=of_...", "deep_link": "openid-credential-offer://?credential_offer=..." }

3. Ready-to-copy credential offer JSON

Two sample offers ship in /downloads/eu-wallet/:

Wallet-provider setup

Wallet providers publish the public keys that sign HAIP section 5.11 Wallet Attestation JWTs, so RPs can enforce that a presentation actually came from a specific wallet product.

1. Publish your JWKS

Static file at https://<YOUR_WALLET_DOMAIN>/.well-known/wallet-provider.jwks.json. A shape sample lives at wallet-provider-jwks.json.

2. Deposit at the tenant

The tenant operator drops the JWKS (or the equivalent X.509 PEM) under:

App_Data/<tenant>/trust/wallet-providers/<wallet-provider-id>.jwks.json

3. Enforce Wallet Attestation

Set Oidc:WalletAttestationRequired=true on the tenant to reject presentations that lack a valid HAIP §5.11 attestation JWT. The testscripts/wallet-attestation-smoke.py probe exercises the full path.

Trust-anchor setup

Verifier tenants need three distinct trust stores: the EU List of Trusted Lists (LOTL) for eIDAS certificate chains, an SD-JWT VC issuer set, and an mDoc issuer set. Each stores its inputs under App_Data/<tenant>/trust/ as PEM / JSON / DER.

The end-to-end operator walk-through, including nightly reconciler + wacs cert refresh, lives on the dedicated HAIP operator setup page. This section is intentionally short: the operator page is the source of truth.

Integrate in minutes

Copy-paste against your own tenant — replace your-tenant.example with your CodeB host. These call the same public endpoints documented in the EU Wallet verifier API and the OIDC provider. No SDK required.

Verify an EU Wallet presentation — OID4VP 1.0

# 1) Start a presentation request and keep its session cookie (OID4VP 1.0 / HAIP)
curl -s -c cj 'https://your-tenant.example/oidc.ashx?action=vp-start&client_id_prefix=x509_hash'
#   -> { "id": "...", "deep_link": "openid4vp://...", "expires_in": 300, "status": "pending" }

# 2) Render deep_link as a QR (desktop) or open it on the phone.
#    The EUDI wallet fetches the signed request and posts an encrypted SD-JWT VC.

# 3) Poll with the same cookie until the user finishes (about every 2 s)
curl -s -b cj 'https://your-tenant.example/oidc.ashx?action=vp-response&id=<id>'
#   waiting  -> HTTP 202 { "ok": false, "status": "pending" }
#   verified -> HTTP 200 { "ok": true, "status": "completed", "user": "...",
#                          "claims": { ... }, "sso_assertion": "<RS256 JWT>" }

Sign in with OpenID Connect — Authorization Code + PKCE

# 1) Discover endpoints
curl -s https://your-tenant.example/.well-known/openid-configuration

# 2) Send the user to sign in (PKCE)
#    https://your-tenant.example/oauth2/v1/authorize?response_type=code
#      &client_id=<id>&redirect_uri=<cb>&scope=openid%20profile%20email
#      &code_challenge=<S256>&code_challenge_method=S256&state=<s>&nonce=<n>

# 3) Exchange the code for tokens
curl -s -X POST https://your-tenant.example/oauth2/v1/token \
  -d grant_type=authorization_code -d code=<code> -d redirect_uri=<cb> \
  -d client_id=<id> -d code_verifier=<verifier>
#   -> { "access_token": "...", "id_token": "...", "expires_in": 3600 }

# 4) Read claims
curl -s https://your-tenant.example/oauth2/v1/userinfo -H 'Authorization: Bearer <token>'

Register your client first in the tenant admin (OIDC clients). Full walkthrough: OIDC sign-up how-to.

Issue a credential to a wallet — OID4VCI

# Mint a credential offer in the issuer admin (see Issuer setup above),
# then share the offer URI as a QR for the wallet to scan:
curl -s 'https://your-tenant.example/vci.ashx?action=offer&id=<offer_id>'
#   -> openid-credential-offer://?credential_offer_uri=...

Formats: SD-JWT VC (dc+sd-jwt) and ISO 18013-5 mdoc. See Issuer setup.

Hand it to your coding assistant

No SDK to learn — paste this prompt into your coding assistant and let it scaffold the integration against your stack:

Integrate my app with a CodeB / EUDI identity tenant at https://your-tenant.example.

- Sign-in: OpenID Connect, Authorization Code + PKCE. Read endpoints from
  /.well-known/openid-configuration (authorize/token/userinfo under /oauth2/v1/).
- Verify an EU Digital Identity Wallet presentation: GET oidc.ashx?action=vp-start,
  render the returned deep_link as a QR, then poll oidc.ashx?action=vp-response&id=<id>
  until it returns HTTP 200 with ok:true and the verified claims (HTTP 202 while
  pending). Keep the session cookie set by vp-start and send it on every poll.
- Credentials are SD-JWT VC (dc+sd-jwt) and ISO 18013-5 mdoc, OID4VP 1.0 / HAIP.
- Handle the pending, expired and invalid_vp_token states.

Generate the server and client code in <my stack>. Spec reference: docs.eudi.dev.

Reference: docs.eudi.dev for upstream EU Digital Identity Wallet reference implementations and protocol profiles.

Developer cookbooks: OIDC sign-in - JWT validation - M2M API keys - Webhooks

See also: wallet interoperability matrix · glossary.

Procurement teams: This capability sits inside our shipped EUDIW stack. See EUDIW procurement readiness — Malta for the full response map (sovereign hosting, HSM supply chain, ARF 3.0 self-assessment table, certification-support commitment).

Frequently asked questions

Which specs does CodeB implement for European Digital Identity Wallet integration?

OpenID for Verifiable Presentations (OID4VP) FINAL, OpenID for Verifiable Credential Issuance (OID4VCI) Draft 15, SD-JWT VC (draft-ietf-oauth-sd-jwt-vc), ISO/IEC 18013-5 mso_mdoc, and the High Assurance Interoperability Profile (HAIP). Upstream reference: docs.eudi.dev.

Do you ship official EU Commission endorsement?

No. CodeB is not endorsed by the European Commission. These integration guides implement public EUDI-ecosystem specifications and reference the upstream docs at docs.eudi.dev.

Does the verifier flow enforce Wallet Attestation?

Optional per tenant. Set Oidc:WalletAttestationRequired=true on the tenant to require HAIP section 5.11 wallet attestation on every presentation.