Skip to content

eIDAS 2.0 Overview

EXPERIMENTAL — structural validation only, NOT cryptographic verification

The eIDAS module is experimental and off by default. The verifier currently performs structural validation only: it checks the VP token’s format, the nonce binding (against the original presentation request), the credential type, the Level of Assurance, and expiry. It does NOT cryptographically verify credentials — there is no SD-JWT issuer-signature check, no holder key-binding check, no selective-disclosure digest check, and the EU Trust List is not enforced (the issuer check is an advisory lookup against a single reference issuer). Do not use the result for production identity assurance. Every response self-declares this via verification_level: "structural", experimental: true, a warning, and an X-AnvilBase-eIDAS-Experimental: true header. See Experimental status & roadmap below.

AnvilBase ships an optional eIDAS 2.0 module for EU Digital Identity. It lets your application run an OpenID4VP Relying Party flow against EUDI Wallets and, optionally, scaffold credential issuance (as an OpenID4VCI Issuer). The intent is to bring regulated, high-assurance identity to self-hosted apps — but the cryptographic core is not yet built (see below).

It’s built in Rust, configured per project. The EU Trust List integration is currently a best-effort, non-blocking lookup, not enforced trust validation.

What it does today (structural)

  • Verifier (OpenID4VP Relying Party) — runs the OpenID4VP request/callback flow and structurally validates the returned VP token (format, nonce binding, type, LoA, expiry). It does not cryptographically verify the credential. See Verifier.
  • Issuer (OpenID4VCI) — scaffolds credential offers/metadata. See Issuer.
  • Level of Assurance (LoA) enforcement — require Low, Substantial, or High assurance (read from the token claims — not cryptographically attested).

What it does NOT do yet (deferred — see roadmap)

  • SD-JWT-VC / mdoc signature verification — no issuer-signature check.
  • Holder key binding — no key-binding-JWT verification.
  • Selective-disclosure digests — disclosed claims are not proven against a signed credential.
  • Enforced EU Trust List — issuer trust is an advisory, non-blocking lookup against one hardcoded reference issuer, not a fetched/enforced Trusted List.
  • ISO mdoc (18013-5) — no COSE/CBOR mobile-document support.
EUDI Wallet → AnvilBase eIDAS module → STRUCTURAL result (experimental)
│ │
├── OpenID4VP flow ├── nonce binding (stored req)
├── VP token DECODE ├── LoA + expiry (from claims)
│ (signature NOT verified) ├── advisory issuer lookup
└── claims extraction └── audit logging

When to use it

Today, the module is suitable only for evaluation, prototyping, and protocol integration testing of the OpenID4VP request/callback flow. Because it does not cryptographically verify credentials, it must not be used for production KYC, account binding, age verification, or any flow that depends on the attributes being trustworthy. Revisit for production use once the cryptographic core lands.

Two surfaces

SurfacePrefixPurpose
Config (management)/api/v1/projects/{id}/eidasenable + configure per project
Flows (data plane)/v1/eidas/{project_id}/*run verify/issue, serve metadata

Configure a project

Enable and configure eIDAS via the management API (or the console eIDAS tab):

Terminal window
curl -X PATCH http://localhost:39001/api/v1/projects/<id>/eidas \
-H "Authorization: Bearer $ANVILBASE_TOKEN" -H "Content-Type: application/json" \
-d '{
"enabled": true,
"verifier": {
"accepted_credentials": ["eu.europa.ec.eudi.pid"],
"required_loa": "substantial",
"trust_list_url": "https://ec.europa.eu/digital-trust-list"
},
"issuer": { "enabled": false, "credential_types": [], "signing_key_id": null }
}'

Read it back:

Terminal window
curl http://localhost:39001/api/v1/projects/<id>/eidas -H "Authorization: Bearer $ANVILBASE_TOKEN"
{
"enabled": true,
"verifier": {
"accepted_credentials": ["eu.europa.ec.eudi.pid"],
"required_loa": "substantial",
"trust_list_url": "https://ec.europa.eu/digital-trust-list",
"callback_url": null
},
"issuer": { "enabled": false, "credential_types": [], "signing_key_id": null }
}
FieldMeaning
enabledexperimental opt-in — turn the eIDAS data plane on for the project. Required: while false, all /v1/eidas/{project_id}/* routes return 403 eidas_experimental_disabled
verifier.accepted_credentialscredential types you’ll accept (e.g. the EUDI PID)
verifier.required_loaminimum assurance: low, substantial, high (read from claims, not attested)
verifier.trust_list_urlEU Trust List endpoint — currently advisory only, not fetched/enforced
issuer.enabledalso scaffold credential issuance

Experimental gate

The eIDAS data plane is gated behind enabled. Until a project explicitly sets settings.eidas.enabled = true, every /v1/eidas/{project_id}/* route (verify, verify/callback, issue, and both .well-known metadata endpoints) returns HTTP 403 with a structured eidas_experimental_disabled message. Once enabled, every response also carries:

  • the response header X-AnvilBase-eIDAS-Experimental: true, and
  • a body envelope {"experimental": true, "warning": "EXPERIMENTAL: structural validation only — not cryptographic credential verification; do not use for production identity assurance", ...}.

This makes it impossible to use the verify/issue endpoints without the response self-declaring that it is experimental and structural-only.

Metadata endpoints

Wallets discover your capabilities through standard well-known endpoints, served per project:

GET /v1/eidas/<project_id>/.well-known/openid4vp # verifier metadata
GET /v1/eidas/<project_id>/.well-known/openid-credential-issuer # issuer metadata

Experimental status & roadmap

The module is experimental because its cryptographic core is intentionally not yet implemented. What runs today is structural validation (format, nonce binding, type, LoA, expiry). The deferred, tracked work to make eIDAS production-grade is:

Deferred capabilityWhat it adds
SD-JWT-VC issuer-signature verificationresolve the issuer key (x5c / JWKS / DID) and verify the SD-JWT signature
Holder key binding (KB-JWT)prove the wallet holds the credential’s key, bound to the request nonce/audience
Selective-disclosure digestsrecompute and match _sd digests so disclosed claims provably belong to the signed credential
Enforced EU Trust Listfetch + cache the official Trusted List and make issuer trust a hard, blocking requirement
ISO mdoc (18013-5)COSE/CBOR mobile-document verification (e.g. mobile driving licence)

Deadline driver: the EU mandate requiring the private sector to accept EUDI Wallets takes effect in December 2027 — the cryptographic core must land well before then. This roadmap is tracked in the crate module docs (eidas/src/lib.rs) and in issue #33.

Audit & compliance

Every verification and issuance is recorded in the audit log, giving you an evidentiary trail for compliance reviews. Audit entries for structural verifications carry "verification_level": "structural" and "experimental": true so the trail itself reflects the (non-cryptographic) nature of the check.

Read on: