HAIP 1.0 OID4VP Verifier — conformance self-test results
Independent evidence that the CodeB EU Wallet Verifier passes the OpenID Foundation OID4VP-1.0-FINAL + HAIP-1.0-FINAL Verifier certification profile (alpha), executed by the OIDF-hosted conformance harness on 2026-07-19.
Test plan finished 2026-07-19
9 tests passed · 0 failures · 0 warnings
Self-test result on the OIDF alpha profile, not the OpenID Certified™ mark. Results generated by the OpenID Foundation conformance suite hosted at
certification.openid.net. The OID4VP-1.0-FINAL + HAIP-1.0-FINAL Verifier profile is currently in
alpha self-certification. Formal listing on the
OpenID certified deployments page follows the OIDF submission process; this page attests that the exact EU Wallet Verifier shipped inside every CodeB tenant deployment passes the alpha suite end-to-end without failures or warnings. Formal submission is on the
roadmap.
Deploying the verifier? The three operator-supplied trust-anchor stores (mDoc issuers, HAIP wallet providers, SD-JWT VC LOTL overlay) and the two related tenant settings are documented in the dedicated
HAIP Verifier operator setup runbook, together with post-deploy smoke tests.
Built by Aloaha Limited. Not a fork of any SDK.
Every protocol layer — SD-JWT VC parsing, JWS + KB-JWT signature verification, OpenID4VP request/response, DCQL query builder, direct_post.jwt JWE ECDH-ES, x5c chain validation, OpenID Federation 1.0 entity statements, HAIP client_id prefix x509_hash (as mandated by HAIP 1.0 Final), plus the additional OpenID4VP compatibility prefix x509_san_dns for legacy wallets that pre-date HAIP — is written in-house by the Aloaha Limited engineering team. No eudi-lib-*, no third-party EUDI SDK anywhere in the dependency tree. That translates into three practical guarantees:
- The code belongs to us. Every line of the implementation can be inspected in your own security audit. No closed EUDI libraries that your CISO has to trust on faith. Generic infrastructure libraries (JWT/JWS, HTTP, .NET BCL crypto primitives) are widely-used open-source components; the EUDI-protocol code itself is 100% Aloaha-written.
- Our own delivery calendar. We ship on our own release cadence — not gated on a consortium’s next SDK version, not tied to withdrawal cycles we didn’t choose. CVE patches and trust-policy changes land as soon as we’ve tested them, not on someone else’s schedule.
- Strict standards-based interoperability. The wallet, the verifier and the issuer talk to each other exclusively through published RFCs (RFC 7519 JWT, RFC 7515 JWS, RFC 7516 JWE, RFC 8725 JWT BCP, RFC 9126 PAR) and EUDI protocols (OID4VP 1.0 FINAL, OID4VCI 1.0 Final, HAIP 1.0 FINAL, SIOP v2, OpenID Federation 1.0). Every piece is replaceable — no vendor lock-in, not even between our own components.
0
third-party EUDI SDK deps
MT
built + maintained in Malta
Summary
| Area | What it verifies | Result |
| Happy path | End-to-end DCQL query, JAR, wallet response, JWE decrypt, SD-JWT VC parse, KB-JWT verify, claim mapping | Pass |
Minimal cnf.jwk | Accepts holder-binding JWKs that carry only required fields (kty/crv/x/y), no optional metadata | Pass |
| Issuer signature integrity | Rejects VP whose SD-JWT issuer JWS signature has been tampered with | Pass |
| Key Binding JWT signature | Rejects VP whose KB-JWT signature fails to verify against the credential’s cnf key | Pass |
| Selective-disclosure integrity | Rejects VP where the KB-JWT’s sd_hash does not match the presented SD-JWT bytes | Pass |
| KB-JWT nonce binding | Rejects VP where KB-JWT nonce does not match the authorization-request nonce | Pass |
| KB-JWT audience binding | Rejects VP where KB-JWT aud does not match the verifier client identifier | Pass |
| KB-JWT time skew (past) | Rejects VP whose KB-JWT iat is outside the acceptable freshness window (1 year in the past) | Pass |
| KB-JWT time skew (future) | Rejects VP whose KB-JWT iat is outside the acceptable freshness window (1 year in the future) | Pass |
Evidence
Three independent evidence trails, any one is enough to reproduce the test on your own infrastructure.
Test breakdown — 9 tests, all passed
Every test finished with harness status FINISHED and result PASSED.
Happy path (2)
| Test name | Result |
| oid4vp-1final-verifier-happy-flow | Pass |
| oid4vp-1final-verifier-minimal-cnf-jwk | Pass |
Cryptographic integrity (3)
| Test name | Result |
| oid4vp-1final-verifier-invalid-credential-signature | Pass |
| oid4vp-1final-verifier-invalid-kb-jwt-signature | Pass |
| oid4vp-1final-verifier-invalid-sd-hash | Pass |
Session binding (2)
| Test name | Result |
| oid4vp-1final-verifier-invalid-kb-jwt-nonce | Pass |
| oid4vp-1final-verifier-invalid-kb-jwt-aud | Pass |
Freshness (2)
| Test name | Result |
| oid4vp-1final-verifier-kb-jwt-iat-in-past | Pass |
| oid4vp-1final-verifier-kb-jwt-iat-in-future | Pass |
How to reproduce
- Sign up for a free account at certification.openid.net, create a plan of type “OID4VP-1.0-FINAL + HAIP-1.0-FINAL Verifier” (alpha) with variant
credential_format=sd_jwt_vc and response_mode=direct_post.jwt.
- Configure the plan’s
server section with your CodeB tenant verifier metadata: the authorization endpoint URL, your per-tenant X.509 leaf public key, and your chosen client_id_prefix. HAIP 1.0 Final mandates x509_hash; we additionally support x509_san_dns as an OpenID4VP compatibility mode for legacy wallets (not part of HAIP Final).
- Run all 9 alpha sub-tests. The verifier drives each end-to-end from wallet selection through decrypted-response claim delivery; no manual interaction is needed.
- Download the certification package ZIP from your plan-detail page and compare per-test
results arrays against the JSON bundle linked above.
Roadmap to the OpenID Certified™ mark
Passing the alpha conformance suite is step one. The full path to being listed on the OpenID Foundation certified-implementations page is:
- Done — OID4VP-1.0-FINAL + HAIP-1.0-FINAL Verifier alpha suite,
sd_jwt_vc + direct_post.jwt variant, zero-failure zero-warning run on the OIDF harness.
- In flight — 2026-07-20: growing mDoc / ISO 18013-5 pipeline — foundations shipped (dependency-free CBOR + COSE_Sign1 + mDoc primitives in wallet +
MDocIssuer + MDocVerifier; wallet-side QR camera scanner via BarcodeDetector; OID4VCI code-flow with RFC 9126 PAR + PKCE + wallet-clients.json whitelist alongside the pre-authorized_code grant). End-to-end trust anchors under App_Data/<tenant>/trust/mdoc-issuers/ still operator-supplied; empty directory returns HTTP 501 mdoc_verify_not_configured.
- Recent updates 2026-07-20 — CWT proof-of-possession (RFC 8747) accepted alongside JWT proofs on the mDoc mint endpoint; per-tenant wallet
client_id whitelist via App_Data/<tenant>/wallet-clients.json (5-min cache, hardcoded fallback); terser-minified wallet PWA modules replace the previous copy-only .min twins; a semantic App_Code precompile-check tool (testscripts/App_Code-precompile-check.py) gates every C# 5-safe edit before deploy. Nothing here has been re-run through the OIDF harness — the alpha-suite pass on line 1 above is the last certified evidence.
- Recent updates 2026-07-22 — round3b wallet attestation — HAIP §5.11 Wallet Attestation JWT verification wired into the verifier (
App_Code/WalletAttestationVerifier.cs + WalletAttestationPopVerifier.cs). The verifier accepts a wallet_attestation JWT via header, form field, or JSON envelope; signature is checked against operator-loaded wallet-provider public keys under App_Data/<tenant>/trust/wallet-providers/*.jwks.json (or *.pem). If no anchors are configured and a wallet supplies (or the JAR requires) an attestation the verifier returns HTTP 501 wallet_attestation_not_configured instead of silently trusting the JWT. PoP JWT (holder-signed wallet-attestation-pop+jwt with aud=response_uri + nonce=<JAR nonce>) verified when supplied. Verifier mode: mso_mdoc continues to require operator-loaded issuer trust anchors under App_Data/<tenant>/trust/mdoc-issuers/; empty directory returns HTTP 501 mdoc_verify_not_configured. Nothing here has been re-run through the OIDF harness — the alpha-suite pass on line 1 above is the last certified evidence.
- Recent updates 2026-07-22 — ARF-native VCT catalogue — the tenant-scoped issuer (
vci.ashx) now mints the three ARF-defined credential types adopted by the European Digital Identity Wallet reference implementation: urn:eu.europa.ec.eudi:pid:1 (bundled given_name, family_name, birth_date, age_over_18, age_in_years, age_birth_year), urn:eu.europa.ec.eudi:email:1 and urn:eu.europa.ec.eudi:address:1. Aloaha-scoped VCTs remain for concepts with no ARF equivalent today (username, preferred-username, tenant-membership, phone-verified). Legacy Aloaha VCTs that now have an ARF successor return HTTP 404 vct_retired with a structured {vct, successor, hint} body so wallets can migrate without guesswork. PID mint is refused when the signed-in user profile lacks any of {given_name, family_name, birth_date} — the issuer prefers an honest error to a synthetic PID. This is a scope + honesty change, not a certification claim; the alpha-suite pass on line 1 above remains the last independently verified evidence.
- Recent updates 2026-07-22 — OID4VP 1.0 FINAL DCQL feature parity — the verifier now advertises
wallet_attestation_required=true in the JAR when the tenant has configured wallet-provider anchors (OID4VP §5.10 + HAIP §5.11), so wallets know to attach an attestation up-front. The wallet-side matcher shipped alongside the verifier now understands claims[*].values filter arrays, per-credential claim_sets alternative bundles, credential_sets.required=false all-optional handling, and mDoc intent_to_retain (recorded to the audit log so a data-protection officer can review any retention-declaring request). Explicit require_cryptographic_holder_binding is honoured implicitly through the existing KB-JWT / DeviceAuth checks; purpose i18n objects and JSON Schema filter remain on the honest deferral list until the OIDF harness ships coverage for them. None of this has been re-run through the OIDF harness — the alpha-suite pass on line 1 above is the last certified evidence.
- Recent updates 2026-07-22 — SD-JWT VC LOTL overlay split — the SD-JWT VC issuer chain gate in
oidc.ashx (iter-3) now reads its operator overlay from a dedicated App_Data/<tenant>/trust/vc-issuers/*.cer|.crt directory. If that directory is empty or missing, iter-3 falls back to the legacy App_Data/<tenant>/trust/mdoc-issuers/ store used by the mDoc verifier and emits a LOUD [LOTL-CHAIN] WRN overlay-legacy-fallback so operators know to migrate. The mDoc verifier keeps its own trust/mdoc-issuers/ path unchanged. Nothing here has been re-run through the OIDF harness — the alpha-suite pass on line 1 above is the last certified evidence.
- Recent updates 2026-07-26 — ARF TS3 Key Attestation acceptance — the tenant-scoped issuer (
vci.ashx) now accepts Key Attestation JWTs alongside the existing Wallet Instance Attestation. A Key Attestation proves the specific proof-of-possession key was generated in a trusted secure area (StrongBox, Secure Enclave or equivalent); it is carried by the wallet in the OpenID4VCI proof JWT either in the JOSE header (key_attestation) or the payload (attestations[]). Per-tenant mode Vci:KeyAttestationMode = off / optional (default) / require. Trust anchors live under App_Data/<tenant>/trust/key-attestation-issuers/*.pem. Credential Issuer metadata advertises key_attestation_signing_alg_values_supported + key_attestations_required. Only the generic JWT-based shape is verified today; vendor-specific formats (android-key, apple-anonymous, TPM) are deferred. This is a scope + honesty extension; the alpha-suite pass on line 1 above remains the last independently verified evidence.
- Recent updates 2026-07-26 — ARF 3.0 narrative review — the European Digital Identity Wallet Architecture and Reference Framework version 3.0 (published 2026-07-21) has been read against the verifier profile shipped above. The mandatory presentation stack in ARF §5.7 (OpenID4VP + HAIP for SD-JWT VC over
direct_post.jwt) matches what the alpha suite exercises; the mandatory issuance stack in ARF §5.8 (OpenID4VCI + HAIP with wallet-instance-attestation acceptance) matches what vci.ashx exposes today. Registration under Commission Implementing Regulation (EU) 2025/848 (ARF §6.4.2) remains an operator step: access certificates and per-intended-use registration certificates are consumed from operator-loaded per-tenant trust stores when the responsible Member State Registrar issues them; nothing is silently fabricated. W3C Digital Credentials API transport (ARF §5.7.1) and the ARF Zero-Knowledge Proof track (TS4 / TS13 / TS14) are not implemented today — wallets that require them fall back to the shipped OpenID4VP + custom-URI-scheme transport. This is a scope + alignment note, not a certification claim; the alpha-suite pass on line 1 above remains the last independently verified evidence.
- Recent updates 2026-07-26 — JAdES Baseline B + WIA EUDI extensions — per the July 2026 European Digital Identity Wallet implementing rules, the tenant-scoped issuer (
vci.ashx) now validates the ETSI TS 119 182-1 JAdES Baseline B header claims (crit, sigT, x5t#S256, sigPl) on Key Attestation JWTs and advertises both key-attestation+jwt and key-attestation+jades as accepted envelope types in the Credential Issuer metadata. A per-tenant opt-in Vci:KeyAttestationRequireSealed gates the leaf certificate against EKU OID 0.4.0.194112.1.4 (id-kp-EIDASSeal). The Wallet Instance Attestation verifier now accepts the EUDI-specific claims wallet_link, wallet_name, wallet_metadata (with nested wallet_provider + wallet_version), attestation_type, and key_type_ref — presence-optional, strict-shape-if-present, unknown claims logged at DEBUG for forward compatibility. This is a scope + honesty extension; the alpha-suite pass on line 1 above remains the last independently verified evidence.
- Next — run the same suite against the additional variants the profile allows (
request_uri_method=post, mDL credential format) once the OIDF harness advances beyond alpha, and archive each plan.
- Then — submit the plan IDs + OIDF certification fee to the OpenID Foundation using the process at openid.net/certification/instructions/. Listing typically appears within one to two weeks of submission.
- Separate track — OpenID4VCI Issuer conformance for the credential-issuance side. As of the 2026-07-26 round, the tenant-scoped issuer (
vci.ashx) has been migrated to the OID4VCI 1.0 Final wire format (published after Draft 15): dedicated Nonce Endpoint per Final §7.2 (/vci.ashx?nonce), Notification Endpoint per Final §10 (/vci.ashx?notification), Credential Response emitted in the Final credentials[] array shape per §8.3 (with the Draft 15 scalar credential field preserved as a backward-compat fallback). Credential Issuer metadata now advertises nonce_endpoint, notification_endpoint and spec_version = "OID4VCI 1.0". A formal Issuer conformance run against OIDF harness will follow once the corresponding profile is published; today the pass is a self-declared wire alignment against the Final specification.
Capabilities shipped after the 2026-07-19 alpha (not covered by that conformance run)
The 2026-07-19 OIDF alpha-suite pass covered only 9 SD-JWT VC tests on the redirect flow. The features listed below have shipped since and are not yet re-tested against a live conformance harness — that re-run is scheduled and its evidence will be published on this page when complete.
- mDoc / ISO 18013-5 primitives. Dependency-free CBOR + COSE_Sign1 stack,
MDocIssuer + MDocVerifier, wallet-side QR camera scanner via BarcodeDetector.
- HAIP §5.11 Wallet Attestation. Verifier-side
wallet_attestation JWT verification against operator-loaded provider anchors under App_Data/<tenant>/trust/wallet-providers/; PoP JWT verification when supplied.
- ARF TS3 Key Attestation acceptance at
vci.ashx. Modes off / optional / require. Trust anchors under App_Data/<tenant>/trust/key-attestation-issuers/.
- Key Attestation JAdES Baseline B + WIA EUDI extensions. ETSI TS 119 182-1 header validation,
key-attestation+jades envelope type, optional EU-seal EKU gate (Vci:KeyAttestationRequireSealed).
- DCQL
trusted_authorities with type: "aki". Emitted on every DCQL query per OpenID4VP §6 and HAIP 1.0 Final §6; per-tenant mode dcqlTrustedAuthoritiesMode.
- OID4VCI 1.0 Final wire migration. Dedicated Nonce Endpoint (
/vci.ashx?nonce), Notification Endpoint (/vci.ashx?notification), Final credentials[] response shape, Draft-15 scalar credential preserved as backward-compat fallback. Metadata advertises nonce_endpoint, notification_endpoint, spec_version = "OID4VCI 1.0".
- HAIP-strict toggle at the verifier. Rejects unencrypted
direct_post by default (haipStrictMode = TRUE). Per-session override ?strict_haip=0|1 at vp-start; production profile forces strict.
- OAuth Status List (draft-13) credential-status client.
StatusListClient.cs, modes enforce / warn / skip; production profile forces enforce.
- DPoP at VCI
?token and ?credential endpoints. Modes off / optional / enforce, per-tenant via Vci:DpopMode.
attest_jwt_client_auth at VCI ?par and ?token. Per-tenant via Vci:ClientAuthMode.
- Per-tenant
/.well-known/security.txt. Rendered from App_Data/<tenant>/security-txt.json; missing tenant → HTTP 404.
- ETSI TS 119 472-3
issuer_info metadata. Access certificate + registration certificate slots surfaced in Credential Issuer metadata for operator-supplied bundles.
- Per-OIDC-client wallet-claim allowlist.
App_Data/<tenant>/oidc-clients/<cid>/wallet-claim-allowlist.json. Default deny; Oidc:WalletClaimDefaultAllowAll=true as backward-compat escape hatch.
- PID persistence retention TTL.
Oidc:PidRetentionSeconds default 2592000 (30 days). Lazy expiry on read; production profile refuses -1.
- ARF TS7 data-deletion request endpoint and ARF TS8 DPA-report endpoint. Superuser-scoped listing and report at
/oidc.ashx?action=data-deletion-list and ?action=dpa-report.
Each item ships behind the same LOUD [TAG-DIAG] audit logging, atomic-write + .backup sidecars, and per-tenant isolation as the rest of the European Digital Identity Wallet surface. Documentation for each: operator setup runbook, EU Wallet Verifier reference. Companion tenant compliance templates: DPIA · RoPA.
Details about the run
| Certification profile | OID4VP-1.0-FINAL + HAIP-1.0-FINAL Verifier (alpha) |
| Plan name | oid4vp-1final-verifier-haip-test-plan |
| Plan ID | Wa46KCPHMZ5EV |
| Variant | credential_format=sd_jwt_vc, response_mode=direct_post.jwt, client_id_prefix=x509_hash, request_method=request_uri_signed, vp_profile=haip |
| Plan started | 2026-07-18 22:23:21 UTC |
| Plan finished | 2026-07-19 |
| Tests | 9 tests — all PASSED |
| Failures | 0 |
| Warnings | 0 |
| Verifier under test | CodeB EU Wallet Verifier — the same code path shipped in every CodeB tenant deployment, running on production infrastructure at the time of the test |
Related specifications
Last updated 2026-07-26. Related pages:
Operator setup runbook ·
EU Wallet Verifier reference ·
EU Wallet integrations ·
Verifier cookbook ·
OIDC Basic OP conformance ·
API reference ·
Deutsch
See also: wallet interoperability matrix · glossary.
DCQL trusted_authorities (AKI) — supported
The verifier emits trusted_authorities with type: "aki" on every DCQL credential query per OpenID4VP §6 and HAIP 1.0 Final §6. Values are base64url-encoded Subject Key Identifiers of the trust anchors in App_Data/<tenant>/trust/vc-issuers/; per-tenant control via dcqlTrustedAuthoritiesMode (all, explicit, off). Full description: EU Wallet API reference.