@openeudi/openid4vp 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @openeudi/openid4vp
2
2
 
3
- OpenID4VP credential parsing and validation for EUDI Wallets. Supports SD-JWT VC and mDOC credential formats with issuer trust verification, expiry checking, and selective disclosure claim extraction.
3
+ OpenID4VP credential parsing and validation for EUDI Wallets. Supports SD-JWT VC and mDOC credential formats with issuer trust verification, expiry checking, selective disclosure claim extraction, and DCQL-based credential matching.
4
4
 
5
5
  ## Install
6
6
 
@@ -33,39 +33,105 @@ if (result.valid) {
33
33
 
34
34
  ## Authorization requests
35
35
 
36
- Build an OpenID4VP authorization request URI to send to an EUDI Wallet:
36
+ Build an OpenID4VP authorization request URI to send to an EUDI Wallet. The request carries a DCQL query ([Digital Credentials Query Language](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#name-digital-credentials-query-l)) describing the credentials you want:
37
37
 
38
38
  ```ts
39
- import { createAuthorizationRequest } from "@openeudi/openid4vp";
40
-
41
- const request = createAuthorizationRequest({
42
- requestedAttributes: ["age_over_18", "resident_country"],
43
- acceptedFormats: ["sd-jwt-vc", "mdoc"],
44
- responseUri: "https://your-app.com/api/verify/callback",
45
- clientId: "your-client-id",
46
- nonce: crypto.randomUUID(),
39
+ import { buildHaipQuery, createAuthorizationRequest } from "@openeudi/openid4vp";
40
+
41
+ const query = buildHaipQuery({
42
+ credentialId: "pid",
43
+ format: "dc+sd-jwt",
44
+ vctValues: ["https://pid.eu/v1"],
45
+ claims: ["age_over_18"],
47
46
  });
48
47
 
48
+ const request = createAuthorizationRequest(
49
+ {
50
+ clientId: "x509_san_dns:verifier.example.com",
51
+ responseUri: "https://verifier.example.com/cb",
52
+ nonce: crypto.randomUUID(),
53
+ },
54
+ query,
55
+ );
56
+
49
57
  console.log(request.uri);
50
58
  // openid4vp://authorize?response_type=vp_token&response_mode=direct_post&...
51
59
 
52
60
  console.log(request.state);
53
61
  // auto-generated UUID unless you provide one
54
62
 
55
- console.log(request.presentationDefinition);
56
- // OID4VP presentation definition with input descriptors
63
+ console.log(request.dcqlQuery);
64
+ // the DCQL query embedded in the request
57
65
  ```
58
66
 
59
67
  ### AuthorizationRequestInput
60
68
 
61
- | Field | Type | Required | Description |
62
- | --------------------- | -------------------- | -------- | ---------------------------------------------- |
63
- | `requestedAttributes` | `string[]` | Yes | Claims to request (e.g. `age_over_18`) |
64
- | `acceptedFormats` | `CredentialFormat[]` | Yes | `'sd-jwt-vc'` and/or `'mdoc'` |
65
- | `responseUri` | `string` | Yes | Callback URL for the wallet response |
66
- | `clientId` | `string` | Yes | Your verifier client identifier |
67
- | `nonce` | `string` | Yes | Challenge nonce for replay protection |
68
- | `state` | `string` | No | Session state (auto-generated UUID if omitted) |
69
+ | Field | Type | Required | Description |
70
+ | -------------- | -------- | -------- | ---------------------------------------------- |
71
+ | `clientId` | `string` | Yes | Your verifier client identifier |
72
+ | `responseUri` | `string` | Yes | Callback URL for the wallet response |
73
+ | `nonce` | `string` | Yes | Challenge nonce for replay protection |
74
+ | `state` | `string` | No | Session state (auto-generated UUID if omitted) |
75
+
76
+ The second argument is a DCQL `Query` object. Use `buildHaipQuery` (below) or hand-construct one and validate it via `validateHaipQuery`.
77
+
78
+ ## HAIP helpers
79
+
80
+ For the High Assurance Interoperability Profile (HAIP) commonly used by EUDI Wallets:
81
+
82
+ ```ts
83
+ import { buildHaipQuery, validateHaipQuery } from "@openeudi/openid4vp";
84
+
85
+ // Build a HAIP-compliant DCQL query:
86
+ const query = buildHaipQuery({
87
+ credentialId: "pid",
88
+ format: "dc+sd-jwt",
89
+ vctValues: ["https://pid.eu/v1"],
90
+ claims: ["age_over_18", "given_name"],
91
+ });
92
+
93
+ // Or validate a hand-built DCQL query:
94
+ validateHaipQuery(query); // throws HaipValidationError on violation
95
+ ```
96
+
97
+ Supported formats: `dc+sd-jwt` and `mso_mdoc`. Other formats (e.g., `jwt_vc_json`) will be rejected by the validator.
98
+
99
+ Known EUDI doctypes auto-namespace their claim paths (e.g., `org.iso.18013.5.1.mDL` → claims under `org.iso.18013.5.1`). Unknown doctypes use the full doctype string as the namespace.
100
+
101
+ ## Verifying presentations against a query
102
+
103
+ Use `verifyPresentation` to combine crypto/structural verification with DCQL matching in a single call:
104
+
105
+ ```ts
106
+ import { verifyPresentation } from "@openeudi/openid4vp";
107
+
108
+ const result = await verifyPresentation(vpToken, query, {
109
+ nonce,
110
+ trustedCertificates,
111
+ });
112
+
113
+ if (result.valid) {
114
+ console.log("matched claims:", result.match.matches[0].extractedClaims);
115
+ console.log("submission:", result.submission);
116
+ } else {
117
+ console.warn("mismatch reasons:", result.match.unmatched);
118
+ // each entry: { queryId, reason, detail? }
119
+ // reason ∈ { format_mismatch, vct_mismatch, doctype_mismatch, missing_claims, trusted_authority_mismatch, no_credential_found }
120
+ }
121
+ ```
122
+
123
+ Mismatches return `valid: false` — they do not throw. Only crypto/structural failures (malformed VP tokens, invalid signatures, expired credentials) and malformed DCQL queries throw exceptions.
124
+
125
+ ### ParseOptions / VerifyOptions
126
+
127
+ Both `parsePresentation` and `verifyPresentation` accept:
128
+
129
+ - `nonce` (required) — the nonce bound into the VP token at creation time.
130
+ - `trustedCertificates` (required) — the set of trusted issuer certificates for crypto verification.
131
+ - `audience?` — expected audience.
132
+ - `allowedAlgorithms?` — restrict signature algorithms.
133
+ - `skipTrustCheck?` — skip trust-list checks (dev/test only).
134
+ - `expectedDocType?` — for mDOC verification.
69
135
 
70
136
  ## Supported formats
71
137
 
@@ -118,14 +184,6 @@ class MyCustomParser implements ICredentialParser {
118
184
  }
119
185
  ```
120
186
 
121
- ### ParseOptions
122
-
123
- | Field | Type | Description |
124
- | --------------------- | -------------- | ------------------------------------ |
125
- | `trustedCertificates` | `Uint8Array[]` | Issuer certificates to trust |
126
- | `nonce` | `string` | Expected nonce for replay protection |
127
- | `skipTrustCheck` | `boolean?` | Explicit opt-in to skip the trust check. When omitted or `false`, `trustedCertificates` must be non-empty — otherwise parsing throws `MalformedCredentialError`. Use `true` for demo/mock environments. |
128
-
129
187
  ### PresentationResult
130
188
 
131
189
  | Field | Type | Description |
@@ -145,6 +203,7 @@ class MyCustomParser implements ICredentialParser {
145
203
  | `UnsupportedFormatError` | Unsupported credential format: `{format}` | Token format is not SD-JWT VC or mDOC |
146
204
  | `MalformedCredentialError` | Credential structure is malformed | Token cannot be decoded or is structurally invalid |
147
205
  | `NonceValidationError` | Nonce does not match expected value | Key binding JWT nonce does not match |
206
+ | `HaipValidationError` | HAIP query constraint violated | DCQL query fails `validateHaipQuery` |
148
207
 
149
208
  ```ts
150
209
  import { MalformedCredentialError, ExpiredCredentialError } from "@openeudi/openid4vp";
@@ -162,7 +221,7 @@ try {
162
221
 
163
222
  This library implements the **verifier side** of OpenID4VP for SD-JWT VC and mDOC credentials.
164
223
 
165
- **What is implemented (v0.3.x):**
224
+ **What is implemented (v0.4.x):**
166
225
 
167
226
  - SD-JWT VC: full cryptographic verification (issuer JWT signature via x5c, disclosure hashes, key binding JWT signature + sd_hash, nonce check)
168
227
  - mDOC / ISO 18013-5 *mso_mdoc* format: CBOR decoding and claim extraction
@@ -171,7 +230,10 @@ This library implements the **verifier side** of OpenID4VP for SD-JWT VC and mDO
171
230
  - mDOC IssuerSignedItem digest verification
172
231
  - `expectedDocType` ParseOptions to lock the credential type
173
232
  - Algorithm allowlist (ES256/384/512 — ECDSA only per EUDI policy)
174
- - Authorization request builder
233
+ - Authorization request builder with DCQL query
234
+ - DCQL query matching via [@openeudi/dcql](https://www.npmjs.com/package/@openeudi/dcql)
235
+ - HAIP query build/validate helpers
236
+ - `verifyPresentation` — combined crypto + DCQL match in one call
175
237
  - Certificate trust check via byte-equality against a caller-supplied trusted set
176
238
 
177
239
  **What is NOT yet implemented** (planned for follow-up releases — do not assume compliance in production until present):
@@ -179,18 +241,21 @@ This library implements the **verifier side** of OpenID4VP for SD-JWT VC and mDO
179
241
  - X.509 certificate chain building and validation beyond leaf-byte-equality
180
242
  - EU List of Trusted Lists (LOTL) / ETSI TL resolution
181
243
  - Certificate revocation (CRL, OCSP)
182
- - DCQL query / credential matching — see [@openeudi/dcql](https://www.npmjs.com/package/@openeudi/dcql)
183
- - OpenID4VP HAIP (High Assurance Interoperability Profile) constraint validation
184
244
  - OpenID Foundation conformance test suite integration
185
245
  - SIOPv2 (Self-Issued OpenID Provider) identity flows
186
246
 
187
- EUDI Architecture Reference Framework (ARF) alignment: tracks OpenID4VP 1.0 final. HAIP and ARF 1.4+ profile compliance will be added before a stable 1.0.
247
+ EUDI Architecture Reference Framework (ARF) alignment: tracks OpenID4VP 1.0 final. Full ARF 1.4+ profile compliance will be added before a stable 1.0.
188
248
 
189
249
  ## Related packages
190
250
 
191
251
  - **[@openeudi/core](https://www.npmjs.com/package/@openeudi/core)** -- Framework-agnostic EUDI Wallet verification protocol engine with session management and QR code generation.
252
+ - **[@openeudi/dcql](https://www.npmjs.com/package/@openeudi/dcql)** -- DCQL query matching engine used internally by `verifyPresentation`.
192
253
  - **[eIDAS Pro](https://eidas-pro.eu)** -- Managed verification service with admin dashboard, webhook integrations, and plugin support for WooCommerce and Shopify.
193
254
 
255
+ ## Migration from 0.3.x
256
+
257
+ See [CHANGELOG.md](./CHANGELOG.md) for the full 0.4.0 migration guide (breaking changes and new APIs).
258
+
194
259
  ## License
195
260
 
196
261
  [Apache 2.0](./LICENSE)