@openid4vc/openid4vci 0.3.0-alpha-20250224151429

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/dist/index.mjs ADDED
@@ -0,0 +1,2124 @@
1
+ // src/index.ts
2
+ import { getGlobalConfig as getGlobalConfig2, setGlobalConfig } from "@openid4vc/utils";
3
+
4
+ // src/credential-request/credential-request-configurations.ts
5
+ import { arrayEqualsIgnoreOrder } from "@openid4vc/utils";
6
+
7
+ // src/metadata/credential-issuer/credential-issuer-metadata.ts
8
+ import { Oauth2Error, fetchWellKnownMetadata } from "@openid4vc/oauth2";
9
+ import { joinUriParts } from "@openid4vc/utils";
10
+
11
+ // src/metadata/credential-issuer/z-credential-issuer-metadata.ts
12
+ import { zCompactJwt } from "@openid4vc/oauth2";
13
+ import { zHttpsUrl } from "@openid4vc/utils";
14
+ import z9 from "zod";
15
+
16
+ // src/formats/credential/mso-mdoc/z-mso-mdoc.ts
17
+ import z3 from "zod";
18
+
19
+ // src/metadata/credential-issuer/z-credential-configuration-supported-common.ts
20
+ import z2 from "zod";
21
+
22
+ // src/key-attestation/z-key-attestation.ts
23
+ import { zJwk, zJwtHeader, zJwtPayload } from "@openid4vc/oauth2";
24
+ import { zInteger } from "@openid4vc/utils";
25
+ import z from "zod";
26
+ var zKeyAttestationJwtHeader = z.object({
27
+ ...zJwtHeader.shape,
28
+ typ: z.literal("keyattestation+jwt")
29
+ }).passthrough().refine(({ kid, jwk }) => jwk === void 0 || kid === void 0, {
30
+ message: `Both 'jwk' and 'kid' are defined. Only one is allowed`
31
+ }).refine(({ trust_chain, kid }) => !trust_chain || !kid, {
32
+ message: `When 'trust_chain' is provided, 'kid' is required`
33
+ });
34
+ var zIso18045 = z.enum(["iso_18045_high", "iso_18045_moderate", "iso_18045_enhanced-basic", "iso_18045_basic"]);
35
+ var zIso18045OrStringArray = z.array(z.union([zIso18045, z.string()]));
36
+ var zKeyAttestationJwtPayload = z.object({
37
+ ...zJwtPayload.shape,
38
+ iat: zInteger,
39
+ attested_keys: z.array(zJwk),
40
+ key_storage: z.optional(zIso18045OrStringArray),
41
+ user_authentication: z.optional(zIso18045OrStringArray),
42
+ certification: z.optional(z.string())
43
+ }).passthrough();
44
+ var zKeyAttestationJwtPayloadForUse = (use) => z.object({
45
+ ...zKeyAttestationJwtPayload.shape,
46
+ // REQUIRED when used as proof_type.attesation directly
47
+ nonce: use === "proof_type.attestation" ? z.string({
48
+ message: `Nonce must be defined when key attestation is used as 'proof_type.attestation' directly`
49
+ }) : z.optional(z.string()),
50
+ // REQUIRED when used within header of proof_type.jwt
51
+ exp: use === "proof_type.jwt" ? zInteger : z.optional(zInteger)
52
+ }).passthrough();
53
+
54
+ // src/metadata/credential-issuer/z-credential-configuration-supported-common.ts
55
+ var zCredentialConfigurationSupportedClaims = z2.object({
56
+ mandatory: z2.boolean().optional(),
57
+ value_type: z2.string().optional(),
58
+ display: z2.object({
59
+ name: z2.string().optional(),
60
+ locale: z2.string().optional()
61
+ }).passthrough().optional()
62
+ }).passthrough();
63
+ var zCredentialConfigurationSupportedCommon = z2.object({
64
+ format: z2.string(),
65
+ scope: z2.string().optional(),
66
+ cryptographic_binding_methods_supported: z2.array(z2.string()).optional(),
67
+ credential_signing_alg_values_supported: z2.array(z2.string()).optional(),
68
+ proof_types_supported: z2.record(
69
+ z2.union([z2.literal("jwt"), z2.literal("attestation"), z2.string()]),
70
+ z2.object({
71
+ proof_signing_alg_values_supported: z2.array(z2.string()),
72
+ key_attestations_required: z2.object({
73
+ key_storage: zIso18045OrStringArray.optional(),
74
+ user_authentication: zIso18045OrStringArray.optional()
75
+ }).passthrough().optional()
76
+ })
77
+ ).optional(),
78
+ display: z2.array(
79
+ z2.object({
80
+ name: z2.string(),
81
+ locale: z2.string().optional(),
82
+ logo: z2.object({
83
+ // FIXME: make required again, but need to support draft 11 first
84
+ uri: z2.string().optional(),
85
+ alt_text: z2.string().optional()
86
+ }).passthrough().optional(),
87
+ description: z2.string().optional(),
88
+ background_color: z2.string().optional(),
89
+ background_image: z2.object({
90
+ // TODO: should be required, but paradym's metadata is wrong here.
91
+ uri: z2.string().optional()
92
+ }).passthrough().optional(),
93
+ text_color: z2.string().optional()
94
+ }).passthrough()
95
+ ).optional()
96
+ }).passthrough();
97
+
98
+ // src/formats/credential/mso-mdoc/z-mso-mdoc.ts
99
+ var zMsoMdocFormatIdentifier = z3.literal("mso_mdoc");
100
+ var zMsoMdocCredentialIssuerMetadata = z3.object({
101
+ format: zMsoMdocFormatIdentifier,
102
+ doctype: z3.string(),
103
+ claims: z3.optional(zCredentialConfigurationSupportedClaims),
104
+ order: z3.optional(z3.array(z3.string()))
105
+ });
106
+ var zMsoMdocCredentialRequestFormat = z3.object({
107
+ format: zMsoMdocFormatIdentifier,
108
+ doctype: z3.string(),
109
+ claims: z3.optional(zCredentialConfigurationSupportedClaims)
110
+ });
111
+
112
+ // src/formats/credential/sd-jwt-vc/z-sd-jwt-vc.ts
113
+ import z4 from "zod";
114
+ var zSdJwtVcFormatIdentifier = z4.literal("vc+sd-jwt");
115
+ var zSdJwtVcCredentialIssuerMetadata = z4.object({
116
+ vct: z4.string(),
117
+ format: zSdJwtVcFormatIdentifier,
118
+ claims: z4.optional(zCredentialConfigurationSupportedClaims),
119
+ order: z4.optional(z4.array(z4.string()))
120
+ });
121
+ var zSdJwtVcCredentialRequestFormat = z4.object({
122
+ format: zSdJwtVcFormatIdentifier,
123
+ vct: z4.string(),
124
+ claims: z4.optional(zCredentialConfigurationSupportedClaims)
125
+ });
126
+
127
+ // src/formats/credential/w3c-vc/z-w3c-ldp-vc.ts
128
+ import z6 from "zod";
129
+
130
+ // src/formats/credential/w3c-vc/z-w3c-vc-common.ts
131
+ import z5 from "zod";
132
+ var zCredentialSubjectLeafType = z5.object({
133
+ mandatory: z5.boolean().optional(),
134
+ value_type: z5.string().optional(),
135
+ display: z5.array(
136
+ z5.object({
137
+ name: z5.string().optional(),
138
+ locale: z5.string().optional()
139
+ }).passthrough()
140
+ ).optional()
141
+ }).passthrough();
142
+ var zClaimValueSchema = z5.union([z5.array(z5.any()), z5.record(z5.string(), z5.any()), zCredentialSubjectLeafType]);
143
+ var zW3cVcCredentialSubject = z5.record(z5.string(), zClaimValueSchema);
144
+ var zW3cVcJsonLdCredentialDefinition = z5.object({
145
+ "@context": z5.array(z5.string()),
146
+ type: z5.array(z5.string()),
147
+ credentialSubject: zW3cVcCredentialSubject.optional()
148
+ }).passthrough();
149
+
150
+ // src/formats/credential/w3c-vc/z-w3c-ldp-vc.ts
151
+ var zLdpVcFormatIdentifier = z6.literal("ldp_vc");
152
+ var zLdpVcCredentialIssuerMetadata = z6.object({
153
+ format: zLdpVcFormatIdentifier,
154
+ credential_definition: zW3cVcJsonLdCredentialDefinition,
155
+ order: z6.array(z6.string()).optional()
156
+ });
157
+ var zLdpVcCredentialIssuerMetadataDraft11 = z6.object({
158
+ order: z6.array(z6.string()).optional(),
159
+ format: zLdpVcFormatIdentifier,
160
+ // Credential definition was spread on top level instead of a separatey property in v11
161
+ // As well as using types instead of type
162
+ "@context": z6.array(z6.string()),
163
+ types: z6.array(z6.string()),
164
+ credentialSubject: zW3cVcCredentialSubject.optional()
165
+ }).passthrough();
166
+ var zLdpVcCredentialIssuerMetadataDraft11To14 = zLdpVcCredentialIssuerMetadataDraft11.transform(
167
+ ({ "@context": context, types, credentialSubject, ...rest }) => ({
168
+ ...rest,
169
+ credential_definition: {
170
+ "@context": context,
171
+ type: types,
172
+ // Prevent weird typing issue with optional vs undefined
173
+ ...credentialSubject ? { credentialSubject } : {}
174
+ }
175
+ })
176
+ );
177
+ var zLdpVcCredentialIssuerMetadataDraft14To11 = zLdpVcCredentialIssuerMetadata.passthrough().transform(({ credential_definition: { type, ...credentialDefinition }, ...rest }) => ({
178
+ ...rest,
179
+ ...credentialDefinition,
180
+ types: type
181
+ })).and(zLdpVcCredentialIssuerMetadataDraft11);
182
+ var zLdpVcCredentialRequestFormat = z6.object({
183
+ format: zLdpVcFormatIdentifier,
184
+ credential_definition: zW3cVcJsonLdCredentialDefinition
185
+ });
186
+ var zLdpVcCredentialRequestDraft11 = z6.object({
187
+ format: zLdpVcFormatIdentifier,
188
+ credential_definition: z6.object({
189
+ "@context": z6.array(z6.string()),
190
+ // credential_definition was using types instead of type in v11
191
+ types: z6.array(z6.string()),
192
+ credentialSubject: zW3cVcCredentialSubject.optional()
193
+ })
194
+ }).passthrough();
195
+ var zLdpVcCredentialRequestDraft11To14 = zLdpVcCredentialRequestDraft11.transform(
196
+ ({ credential_definition: { types, ...restCredentialDefinition }, ...rest }) => ({
197
+ ...rest,
198
+ credential_definition: {
199
+ ...restCredentialDefinition,
200
+ type: types
201
+ }
202
+ })
203
+ );
204
+ var zLdpVcCredentialRequestDraft14To11 = zLdpVcCredentialRequestFormat.passthrough().transform(({ credential_definition: { type, ...restCredentialDefinition }, ...rest }) => ({
205
+ ...rest,
206
+ credential_definition: {
207
+ ...restCredentialDefinition,
208
+ types: type
209
+ }
210
+ })).and(zLdpVcCredentialRequestDraft11);
211
+
212
+ // src/formats/credential/w3c-vc/z-w3c-jwt-vc-json-ld.ts
213
+ import z7 from "zod";
214
+ var zJwtVcJsonLdFormatIdentifier = z7.literal("jwt_vc_json-ld");
215
+ var zJwtVcJsonLdCredentialIssuerMetadata = z7.object({
216
+ format: zJwtVcJsonLdFormatIdentifier,
217
+ credential_definition: zW3cVcJsonLdCredentialDefinition,
218
+ order: z7.optional(z7.array(z7.string()))
219
+ });
220
+ var zJwtVcJsonLdCredentialIssuerMetadataDraft11 = z7.object({
221
+ order: z7.array(z7.string()).optional(),
222
+ format: zJwtVcJsonLdFormatIdentifier,
223
+ // Credential definition was spread on top level instead of a separatey property in v11
224
+ // As well as using types instead of type
225
+ "@context": z7.array(z7.string()),
226
+ types: z7.array(z7.string()),
227
+ credentialSubject: zW3cVcCredentialSubject.optional()
228
+ }).passthrough();
229
+ var zJwtVcJsonLdCredentialIssuerMetadataDraft11To14 = zJwtVcJsonLdCredentialIssuerMetadataDraft11.transform(
230
+ ({ "@context": context, types, credentialSubject, ...rest }) => ({
231
+ ...rest,
232
+ credential_definition: {
233
+ "@context": context,
234
+ type: types,
235
+ // Prevent weird typing issue with optional vs undefined
236
+ ...credentialSubject ? { credentialSubject } : {}
237
+ }
238
+ })
239
+ );
240
+ var zJwtVcJsonLdCredentialIssuerMetadataDraft14To11 = zJwtVcJsonLdCredentialIssuerMetadata.passthrough().transform(({ credential_definition: { type, ...credentialDefinition }, ...rest }) => ({
241
+ ...rest,
242
+ ...credentialDefinition,
243
+ types: type
244
+ })).and(zJwtVcJsonLdCredentialIssuerMetadataDraft11);
245
+ var zJwtVcJsonLdCredentialRequestFormat = z7.object({
246
+ format: zJwtVcJsonLdFormatIdentifier,
247
+ credential_definition: zW3cVcJsonLdCredentialDefinition
248
+ });
249
+ var zJwtVcJsonLdCredentialRequestDraft11 = z7.object({
250
+ format: zJwtVcJsonLdFormatIdentifier,
251
+ credential_definition: z7.object({
252
+ "@context": z7.array(z7.string()),
253
+ // credential_definition was using types instead of type in v11
254
+ types: z7.array(z7.string()),
255
+ credentialSubject: z7.optional(zW3cVcCredentialSubject)
256
+ }).passthrough()
257
+ }).passthrough();
258
+ var zJwtVcJsonLdCredentialRequestDraft11To14 = zJwtVcJsonLdCredentialRequestDraft11.transform(
259
+ ({ credential_definition: { types, ...restCredentialDefinition }, ...rest }) => ({
260
+ ...rest,
261
+ credential_definition: {
262
+ ...restCredentialDefinition,
263
+ type: types
264
+ }
265
+ })
266
+ );
267
+ var zJwtVcJsonLdCredentialRequestDraft14To11 = zJwtVcJsonLdCredentialRequestFormat.passthrough().transform(({ credential_definition: { type, ...restCredentialDefinition }, ...rest }) => ({
268
+ ...rest,
269
+ credential_definition: {
270
+ ...restCredentialDefinition,
271
+ types: type
272
+ }
273
+ })).and(zJwtVcJsonLdCredentialRequestDraft11);
274
+
275
+ // src/formats/credential/w3c-vc/z-w3c-jwt-vc-json.ts
276
+ import z8 from "zod";
277
+ var zJwtVcJsonFormatIdentifier = z8.literal("jwt_vc_json");
278
+ var zJwtVcJsonCredentialDefinition = z8.object({
279
+ type: z8.array(z8.string()),
280
+ credentialSubject: zW3cVcCredentialSubject.optional()
281
+ }).passthrough();
282
+ var zJwtVcJsonCredentialIssuerMetadata = z8.object({
283
+ format: zJwtVcJsonFormatIdentifier,
284
+ credential_definition: zJwtVcJsonCredentialDefinition,
285
+ order: z8.array(z8.string()).optional()
286
+ });
287
+ var zJwtVcJsonCredentialIssuerMetadataDraft11 = z8.object({
288
+ format: zJwtVcJsonFormatIdentifier,
289
+ order: z8.array(z8.string()).optional(),
290
+ // Credential definition was spread on top level instead of a separatey property in v11
291
+ // As well as using types instead of type
292
+ types: z8.array(z8.string()),
293
+ credentialSubject: zW3cVcCredentialSubject.optional()
294
+ }).passthrough();
295
+ var zJwtVcJsonCredentialIssuerMetadataDraft11To14 = zJwtVcJsonCredentialIssuerMetadataDraft11.transform(
296
+ ({ types, credentialSubject, ...rest }) => ({
297
+ ...rest,
298
+ credential_definition: {
299
+ type: types,
300
+ // Prevent weird typing issue with optional vs undefined
301
+ ...credentialSubject ? { credentialSubject } : {}
302
+ }
303
+ })
304
+ );
305
+ var zJwtVcJsonCredentialIssuerMetadataDraft14To11 = zJwtVcJsonCredentialIssuerMetadata.passthrough().transform(({ credential_definition: { type, ...credentialDefinition }, ...rest }) => ({
306
+ ...rest,
307
+ types: type,
308
+ ...credentialDefinition
309
+ })).and(zJwtVcJsonCredentialIssuerMetadataDraft11);
310
+ var zJwtVcJsonCredentialRequestFormat = z8.object({
311
+ format: zJwtVcJsonFormatIdentifier,
312
+ credential_definition: zJwtVcJsonCredentialDefinition
313
+ });
314
+ var zJwtVcJsonCredentialRequestDraft11 = z8.object({
315
+ format: zJwtVcJsonFormatIdentifier,
316
+ // Credential definition was spread on top level instead of a separatey property in v11
317
+ // As well as using types instead of type
318
+ types: z8.array(z8.string()),
319
+ credentialSubject: z8.optional(zW3cVcCredentialSubject)
320
+ }).passthrough();
321
+ var zJwtVcJsonCredentialRequestDraft11To14 = zJwtVcJsonCredentialRequestDraft11.transform(
322
+ ({ types, credentialSubject, ...rest }) => {
323
+ return {
324
+ ...rest,
325
+ credential_definition: {
326
+ type: types,
327
+ // Prevent weird typing issue with optional vs undefined
328
+ ...credentialSubject ? { credentialSubject } : {}
329
+ }
330
+ };
331
+ }
332
+ );
333
+ var zJwtVcJsonCredentialRequestDraft14To11 = zJwtVcJsonCredentialRequestFormat.passthrough().transform(({ credential_definition: { type, ...credentialDefinition }, ...rest }) => ({
334
+ ...rest,
335
+ types: type,
336
+ ...credentialDefinition
337
+ })).and(zJwtVcJsonCredentialRequestDraft11);
338
+
339
+ // src/version.ts
340
+ var Openid4vciDraftVersion = /* @__PURE__ */ ((Openid4vciDraftVersion2) => {
341
+ Openid4vciDraftVersion2["Draft14"] = "Draft14";
342
+ Openid4vciDraftVersion2["Draft11"] = "Draft11";
343
+ return Openid4vciDraftVersion2;
344
+ })(Openid4vciDraftVersion || {});
345
+
346
+ // src/metadata/credential-issuer/z-credential-issuer-metadata.ts
347
+ var allCredentialIssuerMetadataFormats = [
348
+ zSdJwtVcCredentialIssuerMetadata,
349
+ zMsoMdocCredentialIssuerMetadata,
350
+ zJwtVcJsonLdCredentialIssuerMetadata,
351
+ zLdpVcCredentialIssuerMetadata,
352
+ zJwtVcJsonCredentialIssuerMetadata
353
+ ];
354
+ var allCredentialIssuerMetadataFormatIdentifiers = allCredentialIssuerMetadataFormats.map(
355
+ (format) => format.shape.format.value
356
+ );
357
+ var zCredentialConfigurationSupportedWithFormats = zCredentialConfigurationSupportedCommon.transform(
358
+ (data, ctx) => {
359
+ if (!allCredentialIssuerMetadataFormatIdentifiers.includes(data.format)) return data;
360
+ const result = z9.object({}).passthrough().and(z9.discriminatedUnion("format", allCredentialIssuerMetadataFormats)).safeParse(data);
361
+ if (result.success) {
362
+ return result.data;
363
+ }
364
+ for (const issue of result.error.issues) {
365
+ ctx.addIssue(issue);
366
+ }
367
+ return z9.NEVER;
368
+ }
369
+ );
370
+ var zCredentialIssuerMetadataDisplayEntry = z9.object({
371
+ name: z9.string().optional(),
372
+ locale: z9.string().optional(),
373
+ logo: z9.object({
374
+ // FIXME: make required again, but need to support draft 11 first
375
+ uri: z9.string().optional(),
376
+ alt_text: z9.string().optional()
377
+ }).passthrough().optional()
378
+ }).passthrough();
379
+ var zCredentialIssuerMetadataDraft14 = z9.object({
380
+ credential_issuer: zHttpsUrl,
381
+ authorization_servers: z9.array(zHttpsUrl).optional(),
382
+ credential_endpoint: zHttpsUrl,
383
+ deferred_credential_endpoint: zHttpsUrl.optional(),
384
+ notification_endpoint: zHttpsUrl.optional(),
385
+ // Added after draft 14, but needed for proper
386
+ nonce_endpoint: zHttpsUrl.optional(),
387
+ credential_response_encryption: z9.object({
388
+ alg_values_supported: z9.array(z9.string()),
389
+ enc_values_supported: z9.array(z9.string()),
390
+ encryption_required: z9.boolean()
391
+ }).passthrough().optional(),
392
+ batch_credential_issuance: z9.object({
393
+ batch_size: z9.number().positive()
394
+ }).passthrough().optional(),
395
+ signed_metadata: zCompactJwt.optional(),
396
+ display: z9.array(zCredentialIssuerMetadataDisplayEntry).optional(),
397
+ credential_configurations_supported: z9.record(z9.string(), zCredentialConfigurationSupportedWithFormats)
398
+ }).passthrough();
399
+ var zCredentialConfigurationSupportedDraft11To14 = z9.object({
400
+ id: z9.string().optional(),
401
+ format: z9.string(),
402
+ cryptographic_suites_supported: z9.array(z9.string()).optional(),
403
+ display: z9.array(
404
+ z9.object({
405
+ logo: z9.object({
406
+ url: z9.string().url().optional()
407
+ }).passthrough().optional(),
408
+ background_image: z9.object({
409
+ url: z9.string().url().optional()
410
+ }).passthrough().optional()
411
+ }).passthrough()
412
+ ).optional()
413
+ }).passthrough().transform(({ cryptographic_suites_supported, display, id, ...rest }) => ({
414
+ ...rest,
415
+ ...cryptographic_suites_supported ? { credential_signing_alg_values_supported: cryptographic_suites_supported } : {},
416
+ ...display ? {
417
+ display: display.map(({ logo, background_image, ...displayRest }) => ({
418
+ ...displayRest,
419
+ // url became uri and also required
420
+ // so if there's no url in the logo, we remove the whole logo object
421
+ ...logo?.url ? {
422
+ // TODO: we should add the other params from logo as well
423
+ logo: {
424
+ uri: logo.url
425
+ }
426
+ } : {},
427
+ // TODO: we should add the other params from background_image as well
428
+ // url became uri and also required
429
+ // so if there's no url in the background_image, we remove the whole logo object
430
+ ...background_image?.url ? {
431
+ background_image: {
432
+ uri: background_image.url
433
+ }
434
+ } : {}
435
+ }))
436
+ } : {}
437
+ })).transform((data, ctx) => {
438
+ const formatSpecificTransformations = {
439
+ [zLdpVcFormatIdentifier.value]: zLdpVcCredentialIssuerMetadataDraft11To14,
440
+ [zJwtVcJsonFormatIdentifier.value]: zJwtVcJsonCredentialIssuerMetadataDraft11To14,
441
+ [zJwtVcJsonLdFormatIdentifier.value]: zJwtVcJsonLdCredentialIssuerMetadataDraft11To14
442
+ };
443
+ if (!Object.keys(formatSpecificTransformations).includes(data.format)) return data;
444
+ const schema = formatSpecificTransformations[data.format];
445
+ const result = schema.safeParse(data);
446
+ if (result.success) return result.data;
447
+ for (const issue of result.error.issues) {
448
+ ctx.addIssue(issue);
449
+ }
450
+ return z9.NEVER;
451
+ }).pipe(zCredentialConfigurationSupportedWithFormats);
452
+ var zCredentialConfigurationSupportedDraft14To11 = zCredentialConfigurationSupportedWithFormats.and(
453
+ z9.object({
454
+ id: z9.string()
455
+ }).passthrough()
456
+ ).transform(({ id, credential_signing_alg_values_supported, display, proof_types_supported, scope, ...rest }) => ({
457
+ ...rest,
458
+ ...credential_signing_alg_values_supported ? { cryptographic_suites_supported: credential_signing_alg_values_supported } : {},
459
+ ...display ? {
460
+ display: display.map(({ logo, background_image, ...displayRest }) => {
461
+ const { uri: logoUri, ...logoRest } = logo ?? {};
462
+ const { uri: backgroundImageUri, ...backgroundImageRest } = background_image ?? {};
463
+ return {
464
+ ...displayRest,
465
+ // draft 11 uses url, draft 13/14 uses uri
466
+ ...logoUri ? { logo: { url: logoUri, ...logoRest } } : {},
467
+ // draft 11 uses url, draft 13/14 uses uri
468
+ ...backgroundImageUri ? { logo: { url: backgroundImageUri, ...backgroundImageRest } } : {}
469
+ };
470
+ })
471
+ } : {},
472
+ id
473
+ })).pipe(
474
+ z9.union([
475
+ zLdpVcCredentialIssuerMetadataDraft14To11,
476
+ zJwtVcJsonCredentialIssuerMetadataDraft14To11,
477
+ zJwtVcJsonLdCredentialIssuerMetadataDraft14To11,
478
+ // To handle unrecognized formats and not error immediately we allow the common format as well
479
+ // but they can't use any of the foramt identifiers that have a specific transformation. This way if a format is
480
+ // has a transformation it NEEDS to use the format specific transformation, and otherwise we fall back to the common validation
481
+ z9.object({
482
+ format: z9.string().refine(
483
+ (input) => ![
484
+ zLdpVcFormatIdentifier.value,
485
+ zJwtVcJsonFormatIdentifier.value,
486
+ zJwtVcJsonLdFormatIdentifier.value
487
+ ].includes(input)
488
+ )
489
+ }).passthrough()
490
+ ])
491
+ );
492
+ var zCredentialIssuerMetadataDraft11To14 = z9.object({
493
+ authorization_server: z9.string().optional(),
494
+ credentials_supported: z9.array(
495
+ z9.object({
496
+ id: z9.string().optional()
497
+ }).passthrough()
498
+ )
499
+ }).passthrough().transform(({ authorization_server, credentials_supported, ...rest }) => {
500
+ return {
501
+ ...rest,
502
+ ...authorization_server ? { authorization_servers: [authorization_server] } : {},
503
+ // Go from array to map but keep v11 structure
504
+ credential_configurations_supported: Object.fromEntries(
505
+ credentials_supported.map((supported) => supported.id ? [supported.id, supported] : void 0).filter((i) => i !== void 0)
506
+ )
507
+ };
508
+ }).pipe(
509
+ z9.object({
510
+ // Update from v11 structrue to v14 structure
511
+ credential_configurations_supported: z9.record(z9.string(), zCredentialConfigurationSupportedDraft11To14)
512
+ }).passthrough()
513
+ ).pipe(zCredentialIssuerMetadataDraft14);
514
+ var zCredentialIssuerMetadataWithDraft11 = zCredentialIssuerMetadataDraft14.transform((issuerMetadata) => ({
515
+ ...issuerMetadata,
516
+ ...issuerMetadata.authorization_servers ? { authorization_server: issuerMetadata.authorization_servers[0] } : {},
517
+ credentials_supported: Object.entries(issuerMetadata.credential_configurations_supported).map(([id, value]) => ({
518
+ ...value,
519
+ id
520
+ }))
521
+ })).pipe(
522
+ zCredentialIssuerMetadataDraft14.extend({
523
+ credentials_supported: z9.array(zCredentialConfigurationSupportedDraft14To11)
524
+ })
525
+ );
526
+ var zCredentialIssuerMetadata = z9.union([
527
+ // First prioritize draft 14 (and 13)
528
+ zCredentialIssuerMetadataDraft14,
529
+ // Then try parsing draft 11 and transform into draft 14
530
+ zCredentialIssuerMetadataDraft11To14
531
+ ]);
532
+ var zCredentialIssuerMetadataWithDraftVersion = z9.union([
533
+ // First prioritize draft 14 (and 13)
534
+ zCredentialIssuerMetadataDraft14.transform((credentialIssuerMetadata) => ({
535
+ credentialIssuerMetadata,
536
+ originalDraftVersion: "Draft14" /* Draft14 */
537
+ })),
538
+ // Then try parsing draft 11 and transform into draft 14
539
+ zCredentialIssuerMetadataDraft11To14.transform((credentialIssuerMetadata) => ({
540
+ credentialIssuerMetadata,
541
+ originalDraftVersion: "Draft11" /* Draft11 */
542
+ }))
543
+ ]);
544
+
545
+ // src/metadata/credential-issuer/credential-issuer-metadata.ts
546
+ var wellKnownCredentialIssuerSuffix = ".well-known/openid-credential-issuer";
547
+ async function fetchCredentialIssuerMetadata(credentialIssuer, fetch) {
548
+ const wellKnownMetadataUrl = joinUriParts(credentialIssuer, [wellKnownCredentialIssuerSuffix]);
549
+ const result = await fetchWellKnownMetadata(wellKnownMetadataUrl, zCredentialIssuerMetadataWithDraftVersion, fetch);
550
+ if (result && result.credentialIssuerMetadata.credential_issuer !== credentialIssuer) {
551
+ throw new Oauth2Error(
552
+ `The 'credential_issuer' parameter '${result.credentialIssuerMetadata.credential_issuer}' in the well known credential issuer metadata at '${wellKnownMetadataUrl}' does not match the provided credential issuer '${credentialIssuer}'.`
553
+ );
554
+ }
555
+ return result;
556
+ }
557
+ function extractKnownCredentialConfigurationSupportedFormats(credentialConfigurationsSupported) {
558
+ return Object.fromEntries(
559
+ Object.entries(credentialConfigurationsSupported).filter(
560
+ (entry) => allCredentialIssuerMetadataFormatIdentifiers.includes(entry[1].format)
561
+ )
562
+ );
563
+ }
564
+
565
+ // src/credential-request/credential-request-configurations.ts
566
+ function getCredentialConfigurationsMatchingRequestFormat({
567
+ requestFormat,
568
+ credentialConfigurations
569
+ }) {
570
+ const knownCredentialConfigurations = extractKnownCredentialConfigurationSupportedFormats(credentialConfigurations);
571
+ return Object.fromEntries(
572
+ Object.entries(knownCredentialConfigurations).filter(([, credentialConfiguration]) => {
573
+ if (credentialConfiguration.format !== requestFormat.format) return false;
574
+ const r = requestFormat;
575
+ const c = credentialConfiguration;
576
+ if ((c.format === "ldp_vc" || c.format === "jwt_vc_json-ld") && r.format === c.format) {
577
+ return arrayEqualsIgnoreOrder(r.credential_definition.type, c.credential_definition.type) && arrayEqualsIgnoreOrder(r.credential_definition["@context"], c.credential_definition["@context"]);
578
+ }
579
+ if (c.format === "jwt_vc_json" && r.format === c.format) {
580
+ return arrayEqualsIgnoreOrder(r.credential_definition.type, c.credential_definition.type);
581
+ }
582
+ if (c.format === "vc+sd-jwt" && r.format === c.format) {
583
+ return r.vct === c.vct;
584
+ }
585
+ if (c.format === "mso_mdoc" && r.format === c.format) {
586
+ return r.doctype === c.doctype;
587
+ }
588
+ return false;
589
+ })
590
+ );
591
+ }
592
+
593
+ // src/error/Openid4vciError.ts
594
+ var Openid4vciError = class extends Error {
595
+ constructor(message, options) {
596
+ const errorMessage = message ?? "Unknown error occured.";
597
+ const causeMessage = options?.cause instanceof Error ? ` ${options.cause.message}` : options?.cause ? ` ${options?.cause}` : "";
598
+ super(`${errorMessage}${causeMessage}`);
599
+ this.cause = options?.cause;
600
+ }
601
+ };
602
+
603
+ // src/error/Openid4vciRetrieveCredentialsError.ts
604
+ var Openid4vciRetrieveCredentialsError = class extends Openid4vciError {
605
+ constructor(message, response, responseText) {
606
+ super(
607
+ `${message}
608
+ ${JSON.stringify(response.credentialResponseResult?.data ?? response.credentialErrorResponseResult?.data ?? responseText, null, 2)}`
609
+ );
610
+ this.response = response;
611
+ }
612
+ };
613
+
614
+ // src/error/Openid4vciSendNotificationError.ts
615
+ var Openid4vciSendNotificationError = class extends Openid4vciError {
616
+ constructor(message, response) {
617
+ super(message);
618
+ this.response = response;
619
+ }
620
+ };
621
+
622
+ // src/metadata/credential-issuer/credential-configurations.ts
623
+ import { Oauth2Error as Oauth2Error2 } from "@openid4vc/oauth2";
624
+ import { ValidationError } from "@openid4vc/utils";
625
+ function extractScopesForCredentialConfigurationIds(options) {
626
+ const scopes = /* @__PURE__ */ new Set();
627
+ for (const credentialConfigurationId of options.credentialConfigurationIds) {
628
+ const credentialConfiguration = options.issuerMetadata.credentialIssuer.credential_configurations_supported[credentialConfigurationId];
629
+ if (!credentialConfiguration) {
630
+ throw new Oauth2Error2(
631
+ `Credential configuration with id '${credentialConfigurationId}' not found in metadata from credential issuer '${options.issuerMetadata.credentialIssuer.credential_issuer}'`
632
+ );
633
+ }
634
+ const scope = credentialConfiguration.scope;
635
+ if (scope) scopes.add(scope);
636
+ else if (!scope && options.throwOnConfigurationWithoutScope) {
637
+ throw new Oauth2Error2(
638
+ `Credential configuration with id '${credentialConfigurationId}' does not have a 'scope' configured, and 'throwOnConfigurationWithoutScope' was enabled.`
639
+ );
640
+ }
641
+ }
642
+ return scopes.size > 0 ? Array.from(scopes) : void 0;
643
+ }
644
+ function credentialsSupportedToCredentialConfigurationsSupported(credentialsSupported) {
645
+ const credentialConfigurationsSupported = {};
646
+ for (let index = 0; index < credentialsSupported.length; index++) {
647
+ const credentialSupported = credentialsSupported[index];
648
+ if (!credentialSupported.id) {
649
+ throw new Openid4vciError(
650
+ `Credential supported at index '${index}' does not have an 'id' property. Credential configuration requires the 'id' property as key`
651
+ );
652
+ }
653
+ const parseResult = zCredentialConfigurationSupportedDraft11To14.safeParse(credentialSupported);
654
+ if (!parseResult.success) {
655
+ throw new ValidationError(
656
+ `Error transforming credential supported with id '${credentialSupported.id}' to credential configuration supported format`,
657
+ parseResult.error
658
+ );
659
+ }
660
+ credentialConfigurationsSupported[credentialSupported.id] = parseResult.data;
661
+ }
662
+ return credentialConfigurationsSupported;
663
+ }
664
+
665
+ // src/Openid4vciClient.ts
666
+ import {
667
+ Oauth2Client,
668
+ Oauth2ClientAuthorizationChallengeError,
669
+ Oauth2Error as Oauth2Error7,
670
+ Oauth2ErrorCodes as Oauth2ErrorCodes2,
671
+ authorizationCodeGrantIdentifier as authorizationCodeGrantIdentifier2,
672
+ getAuthorizationServerMetadataFromList as getAuthorizationServerMetadataFromList2,
673
+ preAuthorizedCodeGrantIdentifier as preAuthorizedCodeGrantIdentifier3
674
+ } from "@openid4vc/oauth2";
675
+
676
+ // src/credential-offer/credential-offer.ts
677
+ import {
678
+ InvalidFetchResponseError,
679
+ Oauth2Error as Oauth2Error3,
680
+ authorizationCodeGrantIdentifier,
681
+ getAuthorizationServerMetadataFromList,
682
+ preAuthorizedCodeGrantIdentifier as preAuthorizedCodeGrantIdentifier2
683
+ } from "@openid4vc/oauth2";
684
+ import {
685
+ ContentType,
686
+ URL,
687
+ URLSearchParams,
688
+ ValidationError as ValidationError2,
689
+ createZodFetcher,
690
+ encodeToBase64Url,
691
+ getQueryParams,
692
+ objectToQueryParams,
693
+ parseWithErrorHandling
694
+ } from "@openid4vc/utils";
695
+
696
+ // src/credential-offer/z-credential-offer.ts
697
+ import {
698
+ preAuthorizedCodeGrantIdentifier
699
+ } from "@openid4vc/oauth2";
700
+ import z11 from "zod";
701
+
702
+ // ../utils/src/validation.ts
703
+ import z10 from "zod";
704
+
705
+ // ../utils/src/config.ts
706
+ var GLOBAL_CONFIG = {
707
+ allowInsecureUrls: false
708
+ };
709
+ function getGlobalConfig() {
710
+ return GLOBAL_CONFIG;
711
+ }
712
+
713
+ // ../utils/src/validation.ts
714
+ var zHttpsUrl2 = z10.string().url().refine(
715
+ (url) => {
716
+ const { allowInsecureUrls } = getGlobalConfig();
717
+ return allowInsecureUrls ? url.startsWith("http://") || url.startsWith("https://") : url.startsWith("https://");
718
+ },
719
+ { message: "url must be an https:// url" }
720
+ );
721
+ var zInteger2 = z10.number().int();
722
+ var zHttpMethod = z10.enum(["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "TRACE", "CONNECT", "PATCH"]);
723
+
724
+ // src/credential-offer/z-credential-offer.ts
725
+ var zTxCode = z11.object({
726
+ input_mode: z11.union([z11.literal("numeric"), z11.literal("text")]).optional(),
727
+ length: z11.number().int().optional(),
728
+ description: z11.string().max(300).optional()
729
+ }).passthrough();
730
+ var zCredentialOfferGrants = z11.object({
731
+ authorization_code: z11.object({
732
+ issuer_state: z11.string().optional(),
733
+ authorization_server: zHttpsUrl2.optional()
734
+ }).passthrough().optional(),
735
+ [preAuthorizedCodeGrantIdentifier]: z11.object({
736
+ "pre-authorized_code": z11.string(),
737
+ tx_code: zTxCode.optional(),
738
+ authorization_server: zHttpsUrl2.optional()
739
+ }).passthrough().optional()
740
+ }).passthrough();
741
+ var zCredentialOfferObjectDraft14 = z11.object({
742
+ credential_issuer: zHttpsUrl2,
743
+ credential_configuration_ids: z11.array(z11.string()),
744
+ grants: z11.optional(zCredentialOfferGrants)
745
+ }).passthrough();
746
+ var zCredentialOfferObjectDraft11To14 = z11.object({
747
+ credential_issuer: zHttpsUrl2,
748
+ // We don't support the inline offer objects from draft 11
749
+ credentials: z11.array(
750
+ z11.string({ message: "Only string credential identifiers are supported for draft 11 credential offers" })
751
+ ),
752
+ grants: z11.optional(
753
+ z11.object({
754
+ // Has extra param in draft 14, but doesn't matter for transform purposes
755
+ authorization_code: zCredentialOfferGrants.shape.authorization_code,
756
+ [preAuthorizedCodeGrantIdentifier]: z11.object({
757
+ "pre-authorized_code": z11.string(),
758
+ user_pin_required: z11.optional(z11.boolean())
759
+ }).passthrough().optional()
760
+ })
761
+ )
762
+ }).passthrough().transform(({ credentials, grants, ...rest }) => {
763
+ const v14 = {
764
+ ...rest,
765
+ credential_configuration_ids: credentials
766
+ };
767
+ if (grants) {
768
+ v14.grants = { ...grants };
769
+ if (grants[preAuthorizedCodeGrantIdentifier]) {
770
+ const { user_pin_required, ...restGrants } = grants[preAuthorizedCodeGrantIdentifier];
771
+ v14.grants[preAuthorizedCodeGrantIdentifier] = {
772
+ ...restGrants
773
+ };
774
+ if (user_pin_required) {
775
+ v14.grants[preAuthorizedCodeGrantIdentifier].tx_code = {
776
+ input_mode: "text"
777
+ };
778
+ }
779
+ }
780
+ }
781
+ return v14;
782
+ }).pipe(zCredentialOfferObjectDraft14);
783
+ var zCredentialOfferObject = z11.union([
784
+ // First prioritize draft 14 (and 13)
785
+ zCredentialOfferObjectDraft14,
786
+ // Then try parsing draft 11 and transform into draft 14
787
+ zCredentialOfferObjectDraft11To14
788
+ ]);
789
+
790
+ // src/credential-offer/credential-offer.ts
791
+ async function resolveCredentialOffer(credentialOffer, options) {
792
+ const parsedQueryParams = getQueryParams(credentialOffer);
793
+ let credentialOfferParseResult;
794
+ if (parsedQueryParams.credential_offer_uri) {
795
+ const fetchWithZod = createZodFetcher(options?.fetch);
796
+ const { response, result } = await fetchWithZod(
797
+ zCredentialOfferObject,
798
+ ContentType.Json,
799
+ parsedQueryParams.credential_offer_uri
800
+ );
801
+ if (!response.ok || !result) {
802
+ throw new InvalidFetchResponseError(
803
+ `Fetching credential offer from '${parsedQueryParams.credential_offer_uri}' resulted in an unsuccesfull response with status '${response.status}'`,
804
+ await response.clone().text(),
805
+ response
806
+ );
807
+ }
808
+ credentialOfferParseResult = result;
809
+ } else if (parsedQueryParams.credential_offer) {
810
+ let credentialOfferJson;
811
+ try {
812
+ credentialOfferJson = JSON.parse(decodeURIComponent(parsedQueryParams.credential_offer));
813
+ } catch (error) {
814
+ throw new Oauth2Error3(`Error parsing JSON from 'credential_offer' param in credential offer '${credentialOffer}'`);
815
+ }
816
+ credentialOfferParseResult = zCredentialOfferObject.safeParse(credentialOfferJson);
817
+ } else {
818
+ throw new Oauth2Error3(`Credential offer did not contain either 'credential_offer' or 'credential_offer_uri' param.`);
819
+ }
820
+ if (credentialOfferParseResult.error) {
821
+ throw new ValidationError2(
822
+ `Error parsing credential offer in draft 11, 13 or 14 format extracted from credential offer '${credentialOffer}'`,
823
+ credentialOfferParseResult.error
824
+ );
825
+ }
826
+ return credentialOfferParseResult.data;
827
+ }
828
+ function determineAuthorizationServerForCredentialOffer(options) {
829
+ const authorizationServers = options.issuerMetadata.credentialIssuer.authorization_servers;
830
+ let authorizationServer;
831
+ if (options.grantAuthorizationServer) {
832
+ authorizationServer = options.grantAuthorizationServer;
833
+ if (!authorizationServers) {
834
+ throw new Oauth2Error3(
835
+ `Credential offer grant contains 'authorization_server' with value '${options.grantAuthorizationServer}' but credential issuer metadata does not have an 'authorization_servers' property to match the value against.`
836
+ );
837
+ }
838
+ if (!authorizationServers.includes(authorizationServer)) {
839
+ throw new Oauth2Error3(
840
+ `Credential offer grant contains 'authorization_server' with value '${options.grantAuthorizationServer}' but credential issuer metadata does not include this authorization server. Available 'authorization_server' values are ${authorizationServers.join(", ")}.`
841
+ );
842
+ }
843
+ } else if (!authorizationServers) {
844
+ authorizationServer = options.issuerMetadata.credentialIssuer.credential_issuer;
845
+ } else {
846
+ if (authorizationServers.length === 0) {
847
+ throw new Oauth2Error3(`Credential issuer metadata has 'authorization_servers' value with length of 0`);
848
+ }
849
+ if (authorizationServers.length > 1) {
850
+ throw new Oauth2Error3(
851
+ `Credential issuer metadata has 'authorization_server' with multiple entries, but the credential offer grant did not specify which authorization server to use.`
852
+ );
853
+ }
854
+ authorizationServer = authorizationServers[0];
855
+ }
856
+ return authorizationServer;
857
+ }
858
+ async function createCredentialOffer(options) {
859
+ const {
860
+ [preAuthorizedCodeGrantIdentifier2]: preAuthorizedCodeGrant,
861
+ [authorizationCodeGrantIdentifier]: authorizationCodeGrant,
862
+ ...restGrants
863
+ } = options.grants;
864
+ const grants = { ...restGrants };
865
+ if (authorizationCodeGrant) {
866
+ determineAuthorizationServerForCredentialOffer({
867
+ issuerMetadata: options.issuerMetadata,
868
+ grantAuthorizationServer: authorizationCodeGrant.authorization_server
869
+ });
870
+ grants[authorizationCodeGrantIdentifier] = authorizationCodeGrant;
871
+ }
872
+ if (preAuthorizedCodeGrant) {
873
+ determineAuthorizationServerForCredentialOffer({
874
+ issuerMetadata: options.issuerMetadata,
875
+ grantAuthorizationServer: preAuthorizedCodeGrant.authorization_server
876
+ });
877
+ grants[preAuthorizedCodeGrantIdentifier2] = {
878
+ ...preAuthorizedCodeGrant,
879
+ "pre-authorized_code": preAuthorizedCodeGrant["pre-authorized_code"] ?? encodeToBase64Url(await options.callbacks.generateRandom(32))
880
+ };
881
+ const txCode = grants[preAuthorizedCodeGrantIdentifier2].tx_code;
882
+ if (txCode && options.issuerMetadata.originalDraftVersion === "Draft11" /* Draft11 */) {
883
+ grants[preAuthorizedCodeGrantIdentifier2].user_pin_required = txCode !== void 0;
884
+ }
885
+ }
886
+ const idsNotInMetadata = options.credentialConfigurationIds.filter(
887
+ (id) => options.issuerMetadata.credentialIssuer.credential_configurations_supported[id] === void 0
888
+ );
889
+ if (idsNotInMetadata.length > 0) {
890
+ throw new Oauth2Error3(
891
+ `Credential configuration ids ${idsNotInMetadata} not found in the credential issuer metadata 'credential_configurations_supported'. Available ids are ${Object.keys(options.issuerMetadata.credentialIssuer.credential_configurations_supported).join(", ")}.`
892
+ );
893
+ }
894
+ const credentialOfferScheme = options.credentialOfferScheme ?? "openid-credential-offer://";
895
+ const credentialOfferObject = parseWithErrorHandling(zCredentialOfferObject, {
896
+ credential_issuer: options.issuerMetadata.credentialIssuer.credential_issuer,
897
+ credential_configuration_ids: options.credentialConfigurationIds,
898
+ grants,
899
+ ...options.additionalPayload
900
+ });
901
+ if (options.issuerMetadata.originalDraftVersion === "Draft11" /* Draft11 */) {
902
+ credentialOfferObject.credentials = credentialOfferObject.credential_configuration_ids;
903
+ }
904
+ const url = new URL(credentialOfferScheme);
905
+ url.search = `?${new URLSearchParams([
906
+ ...url.searchParams.entries(),
907
+ ...objectToQueryParams({
908
+ credential_offer_uri: options.credentialOfferUri,
909
+ // Only add credential_offer is uri is undefined
910
+ credential_offer: options.credentialOfferUri ? void 0 : credentialOfferObject
911
+ }).entries()
912
+ ]).toString()}`;
913
+ return {
914
+ credentialOffer: url.toString(),
915
+ credentialOfferObject
916
+ };
917
+ }
918
+
919
+ // src/credential-request/format-payload.ts
920
+ import { zIs } from "@openid4vc/utils";
921
+ function getCredentialRequestFormatPayloadForCredentialConfigurationId(options) {
922
+ const credentialConfiguration = options.issuerMetadata.credentialIssuer.credential_configurations_supported[options.credentialConfigurationId];
923
+ if (!credentialConfiguration) {
924
+ throw new Openid4vciError(
925
+ `Could not find credential configuration with id '${options.credentialConfigurationId}' in metadata of credential issuer '${options.issuerMetadata.credentialIssuer.credential_issuer}'.`
926
+ );
927
+ }
928
+ if (zIs(zSdJwtVcCredentialIssuerMetadata, credentialConfiguration)) {
929
+ return {
930
+ format: credentialConfiguration.format,
931
+ vct: credentialConfiguration.vct
932
+ };
933
+ }
934
+ if (zIs(zMsoMdocCredentialIssuerMetadata, credentialConfiguration)) {
935
+ return {
936
+ format: credentialConfiguration.format,
937
+ doctype: credentialConfiguration.doctype
938
+ };
939
+ }
940
+ if (zIs(zLdpVcCredentialIssuerMetadata, credentialConfiguration)) {
941
+ return {
942
+ format: credentialConfiguration.format,
943
+ credential_definition: {
944
+ "@context": credentialConfiguration.credential_definition["@context"],
945
+ type: credentialConfiguration.credential_definition.type
946
+ }
947
+ };
948
+ }
949
+ if (zIs(zJwtVcJsonLdCredentialIssuerMetadata, credentialConfiguration)) {
950
+ return {
951
+ format: credentialConfiguration.format,
952
+ credential_definition: {
953
+ "@context": credentialConfiguration.credential_definition["@context"],
954
+ type: credentialConfiguration.credential_definition.type
955
+ }
956
+ };
957
+ }
958
+ if (zIs(zJwtVcJsonCredentialIssuerMetadata, credentialConfiguration)) {
959
+ return {
960
+ format: credentialConfiguration.format,
961
+ credential_definition: {
962
+ type: credentialConfiguration.credential_definition.type
963
+ }
964
+ };
965
+ }
966
+ throw new Openid4vciError(
967
+ `Unknown format '${credentialConfiguration.format}' in credential configuration with id '${options.credentialConfigurationId}' for credential issuer '${options.issuerMetadata.credentialIssuer.credential_issuer}'`
968
+ );
969
+ }
970
+
971
+ // src/credential-request/retrieve-credentials.ts
972
+ import {
973
+ Oauth2Error as Oauth2Error4,
974
+ resourceRequest
975
+ } from "@openid4vc/oauth2";
976
+ import { ContentType as ContentType2, isResponseContentType, parseWithErrorHandling as parseWithErrorHandling2 } from "@openid4vc/utils";
977
+
978
+ // src/credential-request/z-credential-request.ts
979
+ import z15 from "zod";
980
+
981
+ // src/credential-request/z-credential-request-common.ts
982
+ import { zJwk as zJwk2 } from "@openid4vc/oauth2";
983
+ import z14 from "zod";
984
+
985
+ // src/formats/proof-type/jwt/z-jwt-proof-type.ts
986
+ import { zCompactJwt as zCompactJwt2, zJwtHeader as zJwtHeader2, zJwtPayload as zJwtPayload2 } from "@openid4vc/oauth2";
987
+ import { zHttpsUrl as zHttpsUrl3, zInteger as zInteger3 } from "@openid4vc/utils";
988
+ import z12 from "zod";
989
+ var zJwtProofTypeIdentifier = z12.literal("jwt");
990
+ var jwtProofTypeIdentifier = zJwtProofTypeIdentifier.value;
991
+ var zCredentialRequestProofJwt = z12.object({
992
+ proof_type: zJwtProofTypeIdentifier,
993
+ jwt: zCompactJwt2
994
+ });
995
+ var zCredentialRequestJwtProofTypeHeader = zJwtHeader2.merge(
996
+ z12.object({
997
+ key_attestation: z12.optional(zCompactJwt2),
998
+ typ: z12.literal("openid4vci-proof+jwt")
999
+ })
1000
+ ).passthrough().refine(({ kid, jwk }) => jwk === void 0 || kid === void 0, {
1001
+ message: `Both 'jwk' and 'kid' are defined. Only one is allowed`
1002
+ }).refine(({ trust_chain, kid }) => !trust_chain || !kid, {
1003
+ message: `When 'trust_chain' is provided, 'kid' is required`
1004
+ });
1005
+ var zCredentialRequestJwtProofTypePayload = z12.object({
1006
+ ...zJwtPayload2.shape,
1007
+ aud: zHttpsUrl3,
1008
+ iat: zInteger3
1009
+ }).passthrough();
1010
+
1011
+ // src/formats/proof-type/attestation/z-attestation-proof-type.ts
1012
+ import { zCompactJwt as zCompactJwt3 } from "@openid4vc/oauth2";
1013
+ import z13 from "zod";
1014
+ var zAttestationProofTypeIdentifier = z13.literal("attestation");
1015
+ var attestationProofTypeIdentifier = zAttestationProofTypeIdentifier.value;
1016
+ var zCredentialRequestProofAttestation = z13.object({
1017
+ proof_type: zAttestationProofTypeIdentifier,
1018
+ attestation: zCompactJwt3
1019
+ });
1020
+ var zCredentialRequestAttestationProofTypePayload = zKeyAttestationJwtPayloadForUse("proof_type.attestation");
1021
+
1022
+ // src/credential-request/z-credential-request-common.ts
1023
+ var zCredentialRequestProofCommon = z14.object({
1024
+ proof_type: z14.string()
1025
+ }).passthrough();
1026
+ var allCredentialRequestProofs = [zCredentialRequestProofJwt, zCredentialRequestProofAttestation];
1027
+ var zCredentialRequestProof = z14.union([
1028
+ zCredentialRequestProofCommon,
1029
+ z14.discriminatedUnion("proof_type", allCredentialRequestProofs)
1030
+ ]);
1031
+ var zCredentialRequestProofsCommon = z14.record(z14.string(), z14.array(z14.unknown()));
1032
+ var zCredentialRequestProofs = z14.object({
1033
+ [zJwtProofTypeIdentifier.value]: z14.optional(z14.array(zCredentialRequestProofJwt.shape.jwt)),
1034
+ [zAttestationProofTypeIdentifier.value]: z14.optional(z14.array(zCredentialRequestProofAttestation.shape.attestation))
1035
+ });
1036
+ var zCredentialRequestCommon = z14.object({
1037
+ proof: zCredentialRequestProof.optional(),
1038
+ proofs: z14.optional(
1039
+ z14.intersection(zCredentialRequestProofsCommon, zCredentialRequestProofs).refine((proofs) => Object.values(proofs).length === 1, {
1040
+ message: `The 'proofs' object in a credential request should contain exactly one attribute`
1041
+ })
1042
+ ),
1043
+ credential_response_encryption: z14.object({
1044
+ jwk: zJwk2,
1045
+ alg: z14.string(),
1046
+ enc: z14.string()
1047
+ }).passthrough().optional()
1048
+ }).passthrough().refine(({ proof, proofs }) => !(proof !== void 0 && proofs !== void 0), {
1049
+ message: `Both 'proof' and 'proofs' are defined. Only one is allowed`
1050
+ });
1051
+
1052
+ // src/credential-request/z-credential-request.ts
1053
+ var allCredentialRequestFormats = [
1054
+ zSdJwtVcCredentialRequestFormat,
1055
+ zMsoMdocCredentialRequestFormat,
1056
+ zLdpVcCredentialRequestFormat,
1057
+ zJwtVcJsonLdCredentialRequestFormat,
1058
+ zJwtVcJsonCredentialRequestFormat
1059
+ ];
1060
+ var allCredentialRequestFormatIdentifiers = allCredentialRequestFormats.map(
1061
+ (format) => format.shape.format.value
1062
+ );
1063
+ var zAuthorizationDetailsCredentialRequest = z15.object({
1064
+ credential_identifier: z15.string(),
1065
+ // Cannot be present if credential identifier is present
1066
+ format: z15.never({ message: "'format' cannot be defined when 'credential_identifier' is set." }).optional()
1067
+ });
1068
+ var zCredentialRequestFormatNoCredentialIdentifier = z15.object({
1069
+ format: z15.string(),
1070
+ credential_identifier: z15.never({ message: "'credential_identifier' cannot be defined when 'format' is set." }).optional()
1071
+ }).passthrough();
1072
+ var zCredenialRequestDraft14WithFormat = zCredentialRequestCommon.and(zCredentialRequestFormatNoCredentialIdentifier).transform((data, ctx) => {
1073
+ if (!allCredentialRequestFormatIdentifiers.includes(data.format)) return data;
1074
+ const result = z15.object({}).passthrough().and(z15.discriminatedUnion("format", allCredentialRequestFormats)).safeParse(data);
1075
+ if (result.success) {
1076
+ return result.data;
1077
+ }
1078
+ for (const issue of result.error.issues) {
1079
+ ctx.addIssue(issue);
1080
+ }
1081
+ return z15.NEVER;
1082
+ });
1083
+ var zCredentialRequestDraft14 = z15.union([
1084
+ zCredenialRequestDraft14WithFormat,
1085
+ zCredentialRequestCommon.and(zAuthorizationDetailsCredentialRequest)
1086
+ ]);
1087
+ var zCredentialRequestDraft11To14 = zCredentialRequestCommon.and(zCredentialRequestFormatNoCredentialIdentifier).transform((data, ctx) => {
1088
+ const formatSpecificTransformations = {
1089
+ [zLdpVcFormatIdentifier.value]: zLdpVcCredentialRequestDraft11To14,
1090
+ [zJwtVcJsonFormatIdentifier.value]: zJwtVcJsonCredentialRequestDraft11To14,
1091
+ [zJwtVcJsonLdFormatIdentifier.value]: zJwtVcJsonLdCredentialRequestDraft11To14
1092
+ };
1093
+ if (!Object.keys(formatSpecificTransformations).includes(data.format)) return data;
1094
+ const schema = formatSpecificTransformations[data.format];
1095
+ const result = schema.safeParse(data);
1096
+ if (result.success) return result.data;
1097
+ for (const issue of result.error.issues) {
1098
+ ctx.addIssue(issue);
1099
+ }
1100
+ return z15.NEVER;
1101
+ }).pipe(zCredentialRequestDraft14);
1102
+ var zCredentialRequestDraft14To11 = zCredentialRequestDraft14.refine(
1103
+ (data) => data.credential_identifier === void 0,
1104
+ `'credential_identifier' is not supported in OpenID4VCI draft 11`
1105
+ ).transform((data, ctx) => {
1106
+ const formatSpecificTransformations = {
1107
+ [zLdpVcFormatIdentifier.value]: zLdpVcCredentialRequestDraft14To11,
1108
+ [zJwtVcJsonFormatIdentifier.value]: zJwtVcJsonCredentialRequestDraft14To11,
1109
+ [zJwtVcJsonLdFormatIdentifier.value]: zJwtVcJsonLdCredentialRequestDraft14To11
1110
+ };
1111
+ if (!Object.keys(formatSpecificTransformations).includes(data.format)) return data;
1112
+ const schema = formatSpecificTransformations[data.format];
1113
+ const result = schema.safeParse(data);
1114
+ if (result.success) return result.data;
1115
+ for (const issue of result.error.issues) {
1116
+ ctx.addIssue(issue);
1117
+ }
1118
+ return z15.NEVER;
1119
+ });
1120
+ var zCredentialRequest = z15.union([zCredentialRequestDraft14, zCredentialRequestDraft11To14]);
1121
+
1122
+ // src/credential-request/z-credential-response.ts
1123
+ import z17 from "zod";
1124
+
1125
+ // ../oauth2/src/common/z-oauth2-error.ts
1126
+ import z16 from "zod";
1127
+ var Oauth2ErrorCodes = /* @__PURE__ */ ((Oauth2ErrorCodes4) => {
1128
+ Oauth2ErrorCodes4["ServerError"] = "server_error";
1129
+ Oauth2ErrorCodes4["InvalidTarget"] = "invalid_target";
1130
+ Oauth2ErrorCodes4["InvalidRequest"] = "invalid_request";
1131
+ Oauth2ErrorCodes4["InvalidToken"] = "invalid_token";
1132
+ Oauth2ErrorCodes4["InsufficientScope"] = "insufficient_scope";
1133
+ Oauth2ErrorCodes4["InvalidGrant"] = "invalid_grant";
1134
+ Oauth2ErrorCodes4["InvalidClient"] = "invalid_client";
1135
+ Oauth2ErrorCodes4["UnauthorizedClient"] = "unauthorized_client";
1136
+ Oauth2ErrorCodes4["UnsupportedGrantType"] = "unsupported_grant_type";
1137
+ Oauth2ErrorCodes4["InvalidScope"] = "invalid_scope";
1138
+ Oauth2ErrorCodes4["InvalidDpopProof"] = "invalid_dpop_proof";
1139
+ Oauth2ErrorCodes4["UseDpopNonce"] = "use_dpop_nonce";
1140
+ Oauth2ErrorCodes4["RedirectToWeb"] = "redirect_to_web";
1141
+ Oauth2ErrorCodes4["InvalidSession"] = "invalid_session";
1142
+ Oauth2ErrorCodes4["InsufficientAuthorization"] = "insufficient_authorization";
1143
+ Oauth2ErrorCodes4["InvalidCredentialRequest"] = "invalid_credential_request";
1144
+ Oauth2ErrorCodes4["CredentialRequestDenied"] = "credential_request_denied";
1145
+ Oauth2ErrorCodes4["UnsupportedCredentialType"] = "unsupported_credential_type";
1146
+ Oauth2ErrorCodes4["UnsupportedCredentialFormat"] = "unsupported_credential_format";
1147
+ Oauth2ErrorCodes4["InvalidProof"] = "invalid_proof";
1148
+ Oauth2ErrorCodes4["InvalidNonce"] = "invalid_nonce";
1149
+ Oauth2ErrorCodes4["InvalidEncryptionParameters"] = "invalid_encryption_parameters";
1150
+ Oauth2ErrorCodes4["InvalidRequestUri"] = "invalid_request_uri";
1151
+ Oauth2ErrorCodes4["InvalidRequestObject"] = "invalid_request_object";
1152
+ Oauth2ErrorCodes4["RequestNotSupported"] = "request_not_supported";
1153
+ Oauth2ErrorCodes4["RequestUriNotSupported"] = "request_uri_not_supported";
1154
+ Oauth2ErrorCodes4["VpFormatsNotSupported"] = "vp_formats_not_supported";
1155
+ Oauth2ErrorCodes4["AccessDenied"] = "access_denied";
1156
+ Oauth2ErrorCodes4["InvalidPresentationDefinitionUri"] = "invalid_presentation_definition_uri";
1157
+ Oauth2ErrorCodes4["InvalidPresentationDefinitionReference"] = "invalid_presentation_definition_reference";
1158
+ Oauth2ErrorCodes4["InvalidRequestUriMethod"] = "invalid_request_uri_method";
1159
+ Oauth2ErrorCodes4["InvalidTransactionData"] = "invalid_transaction_data";
1160
+ Oauth2ErrorCodes4["WalletUnavailable"] = "wallet_unavailable";
1161
+ return Oauth2ErrorCodes4;
1162
+ })(Oauth2ErrorCodes || {});
1163
+ var zOauth2ErrorResponse = z16.object({
1164
+ error: z16.union([z16.nativeEnum(Oauth2ErrorCodes), z16.string()]),
1165
+ error_description: z16.string().optional(),
1166
+ error_uri: z16.string().optional()
1167
+ }).passthrough();
1168
+
1169
+ // src/credential-request/z-credential-response.ts
1170
+ var zCredentialEncoding = z17.union([z17.string(), z17.record(z17.string(), z17.any())]);
1171
+ var zCredentialResponse = z17.object({
1172
+ credential: z17.optional(zCredentialEncoding),
1173
+ credentials: z17.optional(z17.array(zCredentialEncoding)),
1174
+ transaction_id: z17.string().optional(),
1175
+ c_nonce: z17.string().optional(),
1176
+ c_nonce_expires_in: z17.number().int().optional(),
1177
+ notification_id: z17.string().optional()
1178
+ }).passthrough().refine(
1179
+ (value) => {
1180
+ const { credential, credentials, transaction_id } = value;
1181
+ return [credential, credentials, transaction_id].filter((i) => i !== void 0).length === 1;
1182
+ },
1183
+ {
1184
+ message: `Exactly one of 'credential', 'credentials', or 'transaction_id' MUST be defined.`
1185
+ }
1186
+ );
1187
+ var zCredentialErrorResponse = z17.object({
1188
+ ...zOauth2ErrorResponse.shape,
1189
+ c_nonce: z17.string().optional(),
1190
+ c_nonce_expires_in: z17.number().int().optional()
1191
+ }).passthrough();
1192
+
1193
+ // src/credential-request/retrieve-credentials.ts
1194
+ async function retrieveCredentialsWithFormat(options) {
1195
+ const credentialRequest = {
1196
+ ...options.formatPayload,
1197
+ ...options.additionalRequestPayload,
1198
+ proof: options.proof,
1199
+ proofs: options.proofs
1200
+ };
1201
+ return retrieveCredentials({
1202
+ callbacks: options.callbacks,
1203
+ credentialRequest,
1204
+ issuerMetadata: options.issuerMetadata,
1205
+ accessToken: options.accessToken,
1206
+ dpop: options.dpop
1207
+ });
1208
+ }
1209
+ async function retrieveCredentials(options) {
1210
+ const credentialEndpoint = options.issuerMetadata.credentialIssuer.credential_endpoint;
1211
+ let credentialRequest = parseWithErrorHandling2(
1212
+ zCredentialRequest,
1213
+ options.credentialRequest,
1214
+ "Error validating credential request"
1215
+ );
1216
+ if (credentialRequest.proofs) {
1217
+ const { batch_credential_issuance } = options.issuerMetadata.credentialIssuer;
1218
+ if (!batch_credential_issuance) {
1219
+ throw new Oauth2Error4(
1220
+ `Credential issuer '${options.issuerMetadata.credentialIssuer.credential_issuer}' does not support batch credential issuance using the 'proofs' request property. Only 'proof' is supported.`
1221
+ );
1222
+ }
1223
+ const proofs = Object.values(credentialRequest.proofs)[0];
1224
+ if (proofs.length > batch_credential_issuance.batch_size) {
1225
+ throw new Oauth2Error4(
1226
+ `Credential issuer '${options.issuerMetadata.credentialIssuer.credential_issuer}' supports batch issuance, but the max batch size is '${batch_credential_issuance.batch_size}'. A total of '${proofs.length}' proofs were provided.`
1227
+ );
1228
+ }
1229
+ }
1230
+ if (options.issuerMetadata.originalDraftVersion === "Draft11" /* Draft11 */) {
1231
+ credentialRequest = parseWithErrorHandling2(
1232
+ zCredentialRequestDraft14To11,
1233
+ credentialRequest,
1234
+ `Error transforming credential request from ${"Draft14" /* Draft14 */} to ${"Draft11" /* Draft11 */}`
1235
+ );
1236
+ }
1237
+ const resourceResponse = await resourceRequest({
1238
+ dpop: options.dpop,
1239
+ accessToken: options.accessToken,
1240
+ callbacks: options.callbacks,
1241
+ url: credentialEndpoint,
1242
+ requestOptions: {
1243
+ method: "POST",
1244
+ headers: {
1245
+ "Content-Type": ContentType2.Json
1246
+ },
1247
+ body: JSON.stringify(credentialRequest)
1248
+ }
1249
+ });
1250
+ if (!resourceResponse.ok) {
1251
+ const credentialErrorResponseResult = isResponseContentType(ContentType2.Json, resourceResponse.response) ? zCredentialErrorResponse.safeParse(await resourceResponse.response.clone().json()) : void 0;
1252
+ return {
1253
+ ...resourceResponse,
1254
+ credentialErrorResponseResult
1255
+ };
1256
+ }
1257
+ const credentialResponseResult = isResponseContentType(ContentType2.Json, resourceResponse.response) ? zCredentialResponse.safeParse(await resourceResponse.response.clone().json()) : void 0;
1258
+ if (!credentialResponseResult?.success) {
1259
+ return {
1260
+ ...resourceResponse,
1261
+ ok: false,
1262
+ credentialResponseResult
1263
+ };
1264
+ }
1265
+ return {
1266
+ ...resourceResponse,
1267
+ credentialResponse: credentialResponseResult.data
1268
+ };
1269
+ }
1270
+
1271
+ // src/formats/proof-type/jwt/jwt-proof-type.ts
1272
+ import { decodeJwt as decodeJwt2, isJwkInSet, jwtHeaderFromJwtSigner as jwtHeaderFromJwtSigner2 } from "@openid4vc/oauth2";
1273
+ import { jwtSignerFromJwt as jwtSignerFromJwt2, verifyJwt as verifyJwt2 } from "@openid4vc/oauth2";
1274
+ import { dateToSeconds as dateToSeconds2, parseWithErrorHandling as parseWithErrorHandling4 } from "@openid4vc/utils";
1275
+
1276
+ // src/key-attestation/key-attestation.ts
1277
+ import { decodeJwt, jwtHeaderFromJwtSigner } from "@openid4vc/oauth2";
1278
+ import { jwtSignerFromJwt, verifyJwt } from "@openid4vc/oauth2";
1279
+ import { dateToSeconds, parseWithErrorHandling as parseWithErrorHandling3 } from "@openid4vc/utils";
1280
+ async function verifyKeyAttestationJwt(options) {
1281
+ const { header, payload } = decodeJwt({
1282
+ jwt: options.keyAttestationJwt,
1283
+ headerSchema: zKeyAttestationJwtHeader,
1284
+ payloadSchema: zKeyAttestationJwtPayloadForUse(options.use)
1285
+ });
1286
+ const now = options.now?.getTime() ?? Date.now();
1287
+ if (options.nonceExpiresAt && now > options.nonceExpiresAt.getTime()) {
1288
+ throw new Openid4vciError("Nonce used for key attestation jwt expired");
1289
+ }
1290
+ const { signer } = await verifyJwt({
1291
+ compact: options.keyAttestationJwt,
1292
+ header,
1293
+ payload,
1294
+ signer: jwtSignerFromJwt({ header, payload }),
1295
+ verifyJwtCallback: options.callbacks.verifyJwt,
1296
+ errorMessage: "Error verifiying key attestation jwt",
1297
+ expectedNonce: options.expectedNonce,
1298
+ now: options.now
1299
+ });
1300
+ return {
1301
+ header,
1302
+ payload,
1303
+ signer
1304
+ };
1305
+ }
1306
+
1307
+ // src/formats/proof-type/jwt/jwt-proof-type.ts
1308
+ async function createCredentialRequestJwtProof(options) {
1309
+ const header = parseWithErrorHandling4(zCredentialRequestJwtProofTypeHeader, {
1310
+ ...jwtHeaderFromJwtSigner2(options.signer),
1311
+ key_attestation: options.keyAttestationJwt,
1312
+ typ: "openid4vci-proof+jwt"
1313
+ });
1314
+ const payload = parseWithErrorHandling4(zCredentialRequestJwtProofTypePayload, {
1315
+ nonce: options.nonce,
1316
+ aud: options.credentialIssuer,
1317
+ iat: dateToSeconds2(options.issuedAt),
1318
+ iss: options.clientId
1319
+ });
1320
+ const { jwt, signerJwk } = await options.callbacks.signJwt(options.signer, { header, payload });
1321
+ if (options.keyAttestationJwt) {
1322
+ const decodedKeyAttestation = decodeJwt2({
1323
+ jwt: options.keyAttestationJwt,
1324
+ headerSchema: zKeyAttestationJwtHeader,
1325
+ payloadSchema: zKeyAttestationJwtPayload
1326
+ });
1327
+ const isSigedWithAttestedKey = await isJwkInSet({
1328
+ jwk: signerJwk,
1329
+ jwks: decodedKeyAttestation.payload.attested_keys,
1330
+ callbacks: options.callbacks
1331
+ });
1332
+ if (!isSigedWithAttestedKey) {
1333
+ throw new Openid4vciError(
1334
+ `Credential request jwt proof is not signed with a key in the 'key_attestation' jwt payload 'attested_keys'`
1335
+ );
1336
+ }
1337
+ }
1338
+ return jwt;
1339
+ }
1340
+ async function verifyCredentialRequestJwtProof(options) {
1341
+ const { header, payload } = decodeJwt2({
1342
+ jwt: options.jwt,
1343
+ headerSchema: zCredentialRequestJwtProofTypeHeader,
1344
+ payloadSchema: zCredentialRequestJwtProofTypePayload
1345
+ });
1346
+ const now = options.now?.getTime() ?? Date.now();
1347
+ if (options.nonceExpiresAt && now > options.nonceExpiresAt.getTime()) {
1348
+ throw new Openid4vciError("Nonce used for credential request proof expired");
1349
+ }
1350
+ const { signer } = await verifyJwt2({
1351
+ compact: options.jwt,
1352
+ header,
1353
+ payload,
1354
+ signer: jwtSignerFromJwt2({ header, payload }),
1355
+ verifyJwtCallback: options.callbacks.verifyJwt,
1356
+ errorMessage: "Error verifiying credential request proof jwt",
1357
+ expectedNonce: options.expectedNonce,
1358
+ expectedAudience: options.credentialIssuer,
1359
+ expectedIssuer: options.clientId,
1360
+ now: options.now
1361
+ });
1362
+ let keyAttestationResult = void 0;
1363
+ if (header.key_attestation) {
1364
+ keyAttestationResult = await verifyKeyAttestationJwt({
1365
+ callbacks: options.callbacks,
1366
+ keyAttestationJwt: header.key_attestation,
1367
+ use: "proof_type.jwt"
1368
+ });
1369
+ const isSigedWithAttestedKey = await isJwkInSet({
1370
+ jwk: signer.publicJwk,
1371
+ jwks: keyAttestationResult.payload.attested_keys,
1372
+ callbacks: options.callbacks
1373
+ });
1374
+ if (!isSigedWithAttestedKey) {
1375
+ throw new Openid4vciError(
1376
+ `Credential request jwt proof is not signed with a key in the 'key_attestation' jwt payload 'attested_keys'`
1377
+ );
1378
+ }
1379
+ }
1380
+ return {
1381
+ header,
1382
+ payload,
1383
+ signer,
1384
+ keyAttestation: keyAttestationResult
1385
+ };
1386
+ }
1387
+
1388
+ // src/metadata/fetch-issuer-metadata.ts
1389
+ import {
1390
+ Oauth2Error as Oauth2Error5,
1391
+ fetchAuthorizationServerMetadata,
1392
+ zAuthorizationServerMetadata
1393
+ } from "@openid4vc/oauth2";
1394
+ import { parseWithErrorHandling as parseWithErrorHandling5 } from "@openid4vc/utils";
1395
+ async function resolveIssuerMetadata(credentialIssuer, options) {
1396
+ const allowAuthorizationMetadataFromCredentialIssuerMetadata = options?.allowAuthorizationMetadataFromCredentialIssuerMetadata ?? true;
1397
+ const credentialIssuerMetadataWithDraftVersion = await fetchCredentialIssuerMetadata(credentialIssuer, options?.fetch);
1398
+ if (!credentialIssuerMetadataWithDraftVersion) {
1399
+ throw new Oauth2Error5(`Well known credential issuer metadata for issuer '${credentialIssuer}' not found.`);
1400
+ }
1401
+ const { credentialIssuerMetadata, originalDraftVersion } = credentialIssuerMetadataWithDraftVersion;
1402
+ const authorizationServers = credentialIssuerMetadata.authorization_servers ?? [credentialIssuer];
1403
+ const authoriationServersMetadata = [];
1404
+ for (const authorizationServer of authorizationServers) {
1405
+ if (options?.restrictToAuthorizationServers && !options.restrictToAuthorizationServers.includes(authorizationServer)) {
1406
+ continue;
1407
+ }
1408
+ let authorizationServerMetadata = await fetchAuthorizationServerMetadata(authorizationServer, options?.fetch);
1409
+ if (!authorizationServerMetadata && authorizationServer === credentialIssuer && allowAuthorizationMetadataFromCredentialIssuerMetadata) {
1410
+ authorizationServerMetadata = parseWithErrorHandling5(
1411
+ zAuthorizationServerMetadata,
1412
+ {
1413
+ token_endpoint: credentialIssuerMetadata.token_endpoint,
1414
+ issuer: credentialIssuer
1415
+ },
1416
+ `Well known authorization server metadata for authorization server '${authorizationServer}' not found, and could also not extract required values from the credential issuer metadata as a fallback.`
1417
+ );
1418
+ }
1419
+ if (!authorizationServerMetadata) {
1420
+ throw new Oauth2Error5(
1421
+ `Well known openid configuration or authorization server metadata for authorization server '${authorizationServer}' not found.`
1422
+ );
1423
+ }
1424
+ authoriationServersMetadata.push(authorizationServerMetadata);
1425
+ }
1426
+ return {
1427
+ originalDraftVersion,
1428
+ credentialIssuer: credentialIssuerMetadata,
1429
+ authorizationServers: authoriationServersMetadata
1430
+ };
1431
+ }
1432
+
1433
+ // src/nonce/nonce-request.ts
1434
+ import { InvalidFetchResponseError as InvalidFetchResponseError2 } from "@openid4vc/oauth2";
1435
+ import { ContentType as ContentType3, ValidationError as ValidationError3, createZodFetcher as createZodFetcher2, parseWithErrorHandling as parseWithErrorHandling6 } from "@openid4vc/utils";
1436
+
1437
+ // src/nonce/z-nonce.ts
1438
+ import { zInteger as zInteger4 } from "@openid4vc/utils";
1439
+ import z18 from "zod";
1440
+ var zNonceResponse = z18.object({
1441
+ c_nonce: z18.string(),
1442
+ c_nonce_expires_in: z18.optional(zInteger4)
1443
+ }).passthrough();
1444
+
1445
+ // src/nonce/nonce-request.ts
1446
+ async function requestNonce(options) {
1447
+ const fetchWithZod = createZodFetcher2(options?.fetch);
1448
+ const nonceEndpoint = options.issuerMetadata.credentialIssuer.nonce_endpoint;
1449
+ if (!nonceEndpoint) {
1450
+ throw new Openid4vciError(
1451
+ `Credential issuer '${options.issuerMetadata.credentialIssuer.credential_issuer}' does not have a nonce endpoint.`
1452
+ );
1453
+ }
1454
+ const { response, result } = await fetchWithZod(zNonceResponse, ContentType3.Json, nonceEndpoint, {
1455
+ method: "POST"
1456
+ });
1457
+ if (!response.ok || !result) {
1458
+ throw new InvalidFetchResponseError2(
1459
+ `Requesting nonce from '${nonceEndpoint}' resulted in an unsuccesfull response with status '${response.status}'`,
1460
+ await response.clone().text(),
1461
+ response
1462
+ );
1463
+ }
1464
+ if (!result.success) {
1465
+ throw new ValidationError3("Error parsing nonce response", result.error);
1466
+ }
1467
+ return result.data;
1468
+ }
1469
+ function createNonceResponse(options) {
1470
+ return parseWithErrorHandling6(zNonceResponse, {
1471
+ c_nonce: options.cNonce,
1472
+ c_nonce_expires_in: options.cNonceExpiresIn,
1473
+ ...options.additionalPayload
1474
+ });
1475
+ }
1476
+
1477
+ // src/notification/notification.ts
1478
+ import {
1479
+ Oauth2Error as Oauth2Error6,
1480
+ resourceRequest as resourceRequest2
1481
+ } from "@openid4vc/oauth2";
1482
+ import { ContentType as ContentType4, isResponseContentType as isResponseContentType2, parseWithErrorHandling as parseWithErrorHandling7 } from "@openid4vc/utils";
1483
+
1484
+ // src/notification/z-notification.ts
1485
+ import z19 from "zod";
1486
+ var zNotificationEvent = z19.enum(["credential_accepted", "credential_failure", "credential_deleted"]);
1487
+ var zNotificationRequest = z19.object({
1488
+ notification_id: z19.string(),
1489
+ event: zNotificationEvent,
1490
+ event_description: z19.optional(z19.string())
1491
+ }).passthrough();
1492
+ var zNotificationErrorResponse = z19.object({
1493
+ error: z19.enum(["invalid_notification_id", "invalid_notification_request"])
1494
+ }).passthrough();
1495
+
1496
+ // src/notification/notification.ts
1497
+ async function sendNotifcation(options) {
1498
+ const notificationEndpoint = options.issuerMetadata.credentialIssuer.notification_endpoint;
1499
+ if (!notificationEndpoint) {
1500
+ throw new Oauth2Error6(
1501
+ `Credential issuer '${options.issuerMetadata.credentialIssuer.credential_issuer}' does not have a notification endpiont configured.`
1502
+ );
1503
+ }
1504
+ const notificationRequest = parseWithErrorHandling7(
1505
+ zNotificationRequest,
1506
+ {
1507
+ event: options.notification.event,
1508
+ notification_id: options.notification.notificationId,
1509
+ event_description: options.notification.eventDescription
1510
+ },
1511
+ "Error validating notification request"
1512
+ );
1513
+ const resourceResponse = await resourceRequest2({
1514
+ dpop: options.dpop,
1515
+ accessToken: options.accessToken,
1516
+ callbacks: options.callbacks,
1517
+ url: notificationEndpoint,
1518
+ requestOptions: {
1519
+ method: "POST",
1520
+ headers: {
1521
+ "Content-Type": ContentType4.Json
1522
+ },
1523
+ body: JSON.stringify(notificationRequest)
1524
+ }
1525
+ });
1526
+ if (!resourceResponse.ok) {
1527
+ const notificationErrorResponseResult = isResponseContentType2(ContentType4.Json, resourceResponse.response) ? zNotificationErrorResponse.safeParse(await resourceResponse.response.clone().json()) : void 0;
1528
+ return {
1529
+ ...resourceResponse,
1530
+ notificationErrorResponseResult
1531
+ };
1532
+ }
1533
+ return resourceResponse;
1534
+ }
1535
+
1536
+ // src/Openid4vciClient.ts
1537
+ var AuthorizationFlow = /* @__PURE__ */ ((AuthorizationFlow2) => {
1538
+ AuthorizationFlow2["Oauth2Redirect"] = "Oauth2Redirect";
1539
+ AuthorizationFlow2["PresentationDuringIssuance"] = "PresentationDuringIssuance";
1540
+ return AuthorizationFlow2;
1541
+ })(AuthorizationFlow || {});
1542
+ var Openid4vciClient = class {
1543
+ constructor(options) {
1544
+ this.options = options;
1545
+ this.oauth2Client = new Oauth2Client({
1546
+ callbacks: this.options.callbacks
1547
+ });
1548
+ }
1549
+ getKnownCredentialConfigurationsSupported(credentialIssuerMetadata) {
1550
+ return extractKnownCredentialConfigurationSupportedFormats(
1551
+ credentialIssuerMetadata.credential_configurations_supported
1552
+ );
1553
+ }
1554
+ /**
1555
+ * Resolve a credential offer into a credential offer object, handling both
1556
+ * 'credential_offer' and 'credential_offer_uri' params.
1557
+ */
1558
+ async resolveCredentialOffer(credentialOffer) {
1559
+ return resolveCredentialOffer(credentialOffer, {
1560
+ fetch: this.options.callbacks.fetch
1561
+ });
1562
+ }
1563
+ async resolveIssuerMetadata(credentialIssuer) {
1564
+ return resolveIssuerMetadata(credentialIssuer, {
1565
+ fetch: this.options.callbacks.fetch
1566
+ });
1567
+ }
1568
+ /**
1569
+ * Retrieve an authorization code for a presentation during issuance session
1570
+ *
1571
+ * This can only be called if an authorization challenge was performed before and returned a
1572
+ * `presentation` paramater along with an `auth_session`. If the presentation response included
1573
+ * an `presentation_during_issuance_session` parameter it MUST be included in this request as well.
1574
+ */
1575
+ async retrieveAuthorizationCodeUsingPresentation(options) {
1576
+ if (!options.credentialOffer.grants?.[authorizationCodeGrantIdentifier2]) {
1577
+ throw new Oauth2Error7(`Provided credential offer does not include the 'authorization_code' grant.`);
1578
+ }
1579
+ const authorizationCodeGrant = options.credentialOffer.grants[authorizationCodeGrantIdentifier2];
1580
+ const authorizationServer = determineAuthorizationServerForCredentialOffer({
1581
+ issuerMetadata: options.issuerMetadata,
1582
+ grantAuthorizationServer: authorizationCodeGrant.authorization_server
1583
+ });
1584
+ const authorizationServerMetadata = getAuthorizationServerMetadataFromList2(
1585
+ options.issuerMetadata.authorizationServers,
1586
+ authorizationServer
1587
+ );
1588
+ const oauth2Client = new Oauth2Client({ callbacks: this.options.callbacks });
1589
+ const { authorizationChallengeResponse, dpop } = await oauth2Client.sendAuthorizationChallengeRequest({
1590
+ authorizationServerMetadata,
1591
+ authSession: options.authSession,
1592
+ presentationDuringIssuanceSession: options.presentationDuringIssuanceSession,
1593
+ dpop: options.dpop
1594
+ });
1595
+ return { authorizationChallengeResponse, dpop };
1596
+ }
1597
+ /**
1598
+ * Initiates authorization for credential issuance. It handles the following cases:
1599
+ * - Authorization Challenge
1600
+ * - Pushed Authorization Request
1601
+ * - Regular Authorization url
1602
+ *
1603
+ * In case the authorization challenge request returns an error with `insufficient_authorization`
1604
+ * with a `presentation` field it means the authorization server expects presentation of credentials
1605
+ * before issuance of crednetials. If this is the case, the value in `presentation` should be treated
1606
+ * as an openid4vp authorization request and submitted to the verifier. Once the presentation response
1607
+ * has been submitted, the RP will respnosd with a `presentation_during_issuance_session` parameter.
1608
+ * Together with the `auth_session` parameter returned in this call you can retrieve an `authorization_code`
1609
+ * using
1610
+ */
1611
+ async initiateAuthorization(options) {
1612
+ if (!options.credentialOffer.grants?.[authorizationCodeGrantIdentifier2]) {
1613
+ throw new Oauth2Error7(`Provided credential offer does not include the 'authorization_code' grant.`);
1614
+ }
1615
+ const authorizationCodeGrant = options.credentialOffer.grants[authorizationCodeGrantIdentifier2];
1616
+ const authorizationServer = determineAuthorizationServerForCredentialOffer({
1617
+ issuerMetadata: options.issuerMetadata,
1618
+ grantAuthorizationServer: authorizationCodeGrant.authorization_server
1619
+ });
1620
+ const authorizationServerMetadata = getAuthorizationServerMetadataFromList2(
1621
+ options.issuerMetadata.authorizationServers,
1622
+ authorizationServer
1623
+ );
1624
+ const oauth2Client = new Oauth2Client({ callbacks: this.options.callbacks });
1625
+ try {
1626
+ const result = await oauth2Client.initiateAuthorization({
1627
+ clientId: options.clientId,
1628
+ pkceCodeVerifier: options.pkceCodeVerifier,
1629
+ redirectUri: options.redirectUri,
1630
+ scope: options.scope,
1631
+ additionalRequestPayload: {
1632
+ ...options.additionalRequestPayload,
1633
+ issuer_state: options.credentialOffer?.grants?.authorization_code?.issuer_state
1634
+ },
1635
+ dpop: options.dpop,
1636
+ clientAttestation: options.clientAttestation,
1637
+ resource: options.issuerMetadata.credentialIssuer.credential_issuer,
1638
+ authorizationServerMetadata
1639
+ });
1640
+ return {
1641
+ ...result,
1642
+ authorizationFlow: "Oauth2Redirect" /* Oauth2Redirect */,
1643
+ authorizationServer: authorizationServerMetadata.issuer
1644
+ };
1645
+ } catch (error) {
1646
+ if (error instanceof Oauth2ClientAuthorizationChallengeError && error.errorResponse.error === Oauth2ErrorCodes2.InsufficientAuthorization && error.errorResponse.presentation) {
1647
+ if (!error.errorResponse.auth_session) {
1648
+ throw new Openid4vciError(
1649
+ `Expected 'auth_session' to be defined with authorization challenge response error '${error.errorResponse.error}' and 'presentation' parameter`
1650
+ );
1651
+ }
1652
+ return {
1653
+ authorizationFlow: "PresentationDuringIssuance" /* PresentationDuringIssuance */,
1654
+ openid4vpRequestUrl: error.errorResponse.presentation,
1655
+ authSession: error.errorResponse.auth_session,
1656
+ authorizationServer: authorizationServerMetadata.issuer
1657
+ };
1658
+ }
1659
+ throw error;
1660
+ }
1661
+ }
1662
+ /**
1663
+ * Convenience method around {@link Oauth2Client.createAuthorizationRequestUrl}
1664
+ * but specifically focused on a credential offer
1665
+ */
1666
+ async createAuthorizationRequestUrlFromOffer(options) {
1667
+ if (!options.credentialOffer.grants?.[authorizationCodeGrantIdentifier2]) {
1668
+ throw new Oauth2Error7(`Provided credential offer does not include the 'authorization_code' grant.`);
1669
+ }
1670
+ const authorizationCodeGrant = options.credentialOffer.grants[authorizationCodeGrantIdentifier2];
1671
+ const authorizationServer = determineAuthorizationServerForCredentialOffer({
1672
+ issuerMetadata: options.issuerMetadata,
1673
+ grantAuthorizationServer: authorizationCodeGrant.authorization_server
1674
+ });
1675
+ const authorizationServerMetadata = getAuthorizationServerMetadataFromList2(
1676
+ options.issuerMetadata.authorizationServers,
1677
+ authorizationServer
1678
+ );
1679
+ const { authorizationRequestUrl, pkce, dpop } = await this.oauth2Client.createAuthorizationRequestUrl({
1680
+ authorizationServerMetadata,
1681
+ clientId: options.clientId,
1682
+ additionalRequestPayload: {
1683
+ ...options.additionalRequestPayload,
1684
+ issuer_state: options.credentialOffer?.grants?.authorization_code?.issuer_state
1685
+ },
1686
+ resource: options.issuerMetadata.credentialIssuer.credential_issuer,
1687
+ redirectUri: options.redirectUri,
1688
+ scope: options.scope,
1689
+ pkceCodeVerifier: options.pkceCodeVerifier,
1690
+ clientAttestation: options.clientAttestation,
1691
+ dpop: options.dpop
1692
+ });
1693
+ return {
1694
+ authorizationRequestUrl,
1695
+ pkce,
1696
+ dpop,
1697
+ authorizationServer: authorizationServerMetadata.issuer
1698
+ };
1699
+ }
1700
+ /**
1701
+ * Convenience method around {@link Oauth2Client.retrievePreAuthorizedCodeAccessToken}
1702
+ * but specifically focused on a credential offer
1703
+ */
1704
+ async retrievePreAuthorizedCodeAccessTokenFromOffer({
1705
+ credentialOffer,
1706
+ issuerMetadata,
1707
+ additionalRequestPayload,
1708
+ txCode,
1709
+ dpop,
1710
+ clientAttestation
1711
+ }) {
1712
+ if (!credentialOffer.grants?.[preAuthorizedCodeGrantIdentifier3]) {
1713
+ throw new Oauth2Error7(`The credential offer does not contain the '${preAuthorizedCodeGrantIdentifier3}' grant.`);
1714
+ }
1715
+ if (credentialOffer.grants[preAuthorizedCodeGrantIdentifier3].tx_code && !txCode) {
1716
+ throw new Oauth2Error7(
1717
+ `Retrieving access token requires a 'tx_code' in the request, but the 'txCode' parameter was not provided.`
1718
+ );
1719
+ }
1720
+ const preAuthorizedCode = credentialOffer.grants[preAuthorizedCodeGrantIdentifier3]["pre-authorized_code"];
1721
+ const authorizationServer = determineAuthorizationServerForCredentialOffer({
1722
+ grantAuthorizationServer: credentialOffer.grants[preAuthorizedCodeGrantIdentifier3].authorization_server,
1723
+ issuerMetadata
1724
+ });
1725
+ const authorizationServerMetadata = getAuthorizationServerMetadataFromList2(
1726
+ issuerMetadata.authorizationServers,
1727
+ authorizationServer
1728
+ );
1729
+ const result = await this.oauth2Client.retrievePreAuthorizedCodeAccessToken({
1730
+ authorizationServerMetadata,
1731
+ preAuthorizedCode,
1732
+ txCode,
1733
+ resource: issuerMetadata.credentialIssuer.credential_issuer,
1734
+ additionalRequestPayload,
1735
+ dpop,
1736
+ clientAttestation
1737
+ });
1738
+ return {
1739
+ ...result,
1740
+ authorizationServer
1741
+ };
1742
+ }
1743
+ /**
1744
+ * Convenience method around {@link Oauth2Client.retrieveAuthorizationCodeAccessTokenFrom}
1745
+ * but specifically focused on a credential offer
1746
+ */
1747
+ async retrieveAuthorizationCodeAccessTokenFromOffer({
1748
+ issuerMetadata,
1749
+ additionalRequestPayload,
1750
+ credentialOffer,
1751
+ authorizationCode,
1752
+ pkceCodeVerifier,
1753
+ redirectUri,
1754
+ dpop,
1755
+ clientAttestation
1756
+ }) {
1757
+ if (!credentialOffer.grants?.[authorizationCodeGrantIdentifier2]) {
1758
+ throw new Oauth2Error7(`The credential offer does not contain the '${authorizationCodeGrantIdentifier2}' grant.`);
1759
+ }
1760
+ const authorizationServer = determineAuthorizationServerForCredentialOffer({
1761
+ grantAuthorizationServer: credentialOffer.grants[authorizationCodeGrantIdentifier2].authorization_server,
1762
+ issuerMetadata
1763
+ });
1764
+ const authorizationServerMetadata = getAuthorizationServerMetadataFromList2(
1765
+ issuerMetadata.authorizationServers,
1766
+ authorizationServer
1767
+ );
1768
+ const result = await this.oauth2Client.retrieveAuthorizationCodeAccessToken({
1769
+ authorizationServerMetadata,
1770
+ authorizationCode,
1771
+ pkceCodeVerifier,
1772
+ additionalRequestPayload,
1773
+ dpop,
1774
+ clientAttestation,
1775
+ redirectUri,
1776
+ resource: issuerMetadata.credentialIssuer.credential_issuer
1777
+ });
1778
+ return {
1779
+ ...result,
1780
+ authorizationServer
1781
+ };
1782
+ }
1783
+ /**
1784
+ * Request a nonce to be used in credential request proofs from the `nonce_endpoint`
1785
+ *
1786
+ * @throws Openid4vciError - if no `nonce_endpoint` is configured in the issuer metadata
1787
+ * @thrwos InvalidFetchResponseError - if the nonce endpoint did not return a succesfull response
1788
+ * @throws ValidationError - if validating the nonce response failed
1789
+ */
1790
+ async requestNonce(options) {
1791
+ return requestNonce(options);
1792
+ }
1793
+ /**
1794
+ * Creates the jwt proof payload and header to be included in a credential request.
1795
+ */
1796
+ async createCredentialRequestJwtProof(options) {
1797
+ const credentialConfiguration = options.issuerMetadata.credentialIssuer.credential_configurations_supported[options.credentialConfigurationId];
1798
+ if (!credentialConfiguration) {
1799
+ throw new Openid4vciError(
1800
+ `Credential configuration with '${options.credentialConfigurationId}' not found in 'credential_configurations_supported' from credential issuer '${options.issuerMetadata.credentialIssuer.credential_issuer}'`
1801
+ );
1802
+ }
1803
+ if (credentialConfiguration.proof_types_supported) {
1804
+ if (!credentialConfiguration.proof_types_supported.jwt) {
1805
+ throw new Openid4vciError(
1806
+ `Credential configuration with id '${options.credentialConfigurationId}' does not support the 'jwt' proof type.`
1807
+ );
1808
+ }
1809
+ if (!credentialConfiguration.proof_types_supported.jwt.proof_signing_alg_values_supported.includes(
1810
+ options.signer.alg
1811
+ )) {
1812
+ throw new Openid4vciError(
1813
+ `Credential configuration with id '${options.credentialConfigurationId}' does not support the '${options.signer.alg}' alg for 'jwt' proof type.`
1814
+ );
1815
+ }
1816
+ if (credentialConfiguration.proof_types_supported.jwt.key_attestations_required && !options.keyAttestationJwt) {
1817
+ throw new Openid4vciError(
1818
+ `Credential configuration with id '${options.credentialConfigurationId}' requires key attestations for 'jwt' proof type but no 'keyAttestationJwt' was provided`
1819
+ );
1820
+ }
1821
+ }
1822
+ const jwt = await createCredentialRequestJwtProof({
1823
+ credentialIssuer: options.issuerMetadata.credentialIssuer.credential_issuer,
1824
+ signer: options.signer,
1825
+ clientId: options.clientId,
1826
+ issuedAt: options.issuedAt,
1827
+ nonce: options.nonce,
1828
+ keyAttestationJwt: options.keyAttestationJwt,
1829
+ callbacks: this.options.callbacks
1830
+ });
1831
+ return {
1832
+ jwt
1833
+ };
1834
+ }
1835
+ /**
1836
+ * @throws Openid4vciRetrieveCredentialsError - if an unsuccesfull response or the respnose couldn't be parsed as credential response
1837
+ * @throws ValidationError - if validation of the credential request failed
1838
+ * @throws Openid4vciError - if the `credentialConfigurationId` couldn't be found, or if the the format specific request couldn't be constructed
1839
+ */
1840
+ async retrieveCredentials({
1841
+ issuerMetadata,
1842
+ proof,
1843
+ proofs,
1844
+ credentialConfigurationId,
1845
+ additionalRequestPayload,
1846
+ accessToken,
1847
+ dpop
1848
+ }) {
1849
+ const formatPayload = getCredentialRequestFormatPayloadForCredentialConfigurationId({
1850
+ credentialConfigurationId,
1851
+ issuerMetadata
1852
+ });
1853
+ const credentialResponse = await retrieveCredentialsWithFormat({
1854
+ accessToken,
1855
+ formatPayload,
1856
+ issuerMetadata,
1857
+ additionalRequestPayload,
1858
+ proof,
1859
+ proofs,
1860
+ callbacks: this.options.callbacks,
1861
+ dpop
1862
+ });
1863
+ if (!credentialResponse.ok) {
1864
+ throw new Openid4vciRetrieveCredentialsError(
1865
+ `Error retrieving credentials from '${issuerMetadata.credentialIssuer.credential_issuer}'`,
1866
+ credentialResponse,
1867
+ await credentialResponse.response.clone().text()
1868
+ );
1869
+ }
1870
+ return credentialResponse;
1871
+ }
1872
+ /**
1873
+ * @throws Openid4vciSendNotificationError - if an unsuccesfull response
1874
+ * @throws ValidationError - if validation of the notification request failed
1875
+ */
1876
+ async sendNotification({
1877
+ issuerMetadata,
1878
+ notification,
1879
+ additionalRequestPayload,
1880
+ accessToken,
1881
+ dpop
1882
+ }) {
1883
+ const notificationResponse = await sendNotifcation({
1884
+ accessToken,
1885
+ issuerMetadata,
1886
+ additionalRequestPayload,
1887
+ callbacks: this.options.callbacks,
1888
+ dpop,
1889
+ notification
1890
+ });
1891
+ if (!notificationResponse.ok) {
1892
+ throw new Openid4vciSendNotificationError(
1893
+ `Error sending notification to '${issuerMetadata.credentialIssuer.credential_issuer}'`,
1894
+ notificationResponse
1895
+ );
1896
+ }
1897
+ return notificationResponse;
1898
+ }
1899
+ };
1900
+
1901
+ // src/Openid4vciIssuer.ts
1902
+ import {
1903
+ Oauth2ErrorCodes as Oauth2ErrorCodes3,
1904
+ Oauth2JwtVerificationError,
1905
+ Oauth2ServerErrorResponseError
1906
+ } from "@openid4vc/oauth2";
1907
+ import { ValidationError as ValidationError4, parseWithErrorHandling as parseWithErrorHandling10 } from "@openid4vc/utils";
1908
+
1909
+ // src/credential-request/credential-response.ts
1910
+ import { parseWithErrorHandling as parseWithErrorHandling8 } from "@openid4vc/utils";
1911
+ function createCredentialResponse(options) {
1912
+ const credentialResponse = parseWithErrorHandling8(zCredentialResponse, {
1913
+ c_nonce: options.cNonce,
1914
+ c_nonce_expires_in: options.cNonceExpiresInSeconds,
1915
+ credential: options.credential,
1916
+ credentials: options.credentials,
1917
+ notification_id: options.notificationId,
1918
+ // NOTE `format` is removed in draft 13. For now if a format was requested
1919
+ // we just always return it in the response as well.
1920
+ format: options.credentialRequest.format?.format,
1921
+ ...options.additionalPayload
1922
+ });
1923
+ return credentialResponse;
1924
+ }
1925
+
1926
+ // src/credential-request/parse-credential-request.ts
1927
+ import { parseWithErrorHandling as parseWithErrorHandling9 } from "@openid4vc/utils";
1928
+ import z20 from "zod";
1929
+ function parseCredentialRequest(options) {
1930
+ const credentialRequest = parseWithErrorHandling9(
1931
+ zCredentialRequest,
1932
+ options.credentialRequest,
1933
+ "Error validating credential request"
1934
+ );
1935
+ let proofs = void 0;
1936
+ const knownProofs = zCredentialRequestProofs.strict().safeParse(credentialRequest.proofs);
1937
+ if (knownProofs.success) {
1938
+ proofs = knownProofs.data;
1939
+ }
1940
+ const knownProof = z20.union(allCredentialRequestProofs).safeParse(credentialRequest.proof);
1941
+ if (knownProof.success && knownProof.data.proof_type === jwtProofTypeIdentifier) {
1942
+ proofs = { [jwtProofTypeIdentifier]: [knownProof.data.jwt] };
1943
+ } else if (knownProof.success && knownProof.data.proof_type === attestationProofTypeIdentifier) {
1944
+ proofs = { [attestationProofTypeIdentifier]: [knownProof.data.attestation] };
1945
+ }
1946
+ if (credentialRequest.credential_identifier) {
1947
+ return {
1948
+ credentialIdentifier: credentialRequest.credential_identifier,
1949
+ credentialRequest,
1950
+ proofs
1951
+ };
1952
+ }
1953
+ if (credentialRequest.format && allCredentialRequestFormatIdentifiers.includes(credentialRequest.format)) {
1954
+ return {
1955
+ // Removes all claims that are not specific to this format
1956
+ format: parseWithErrorHandling9(
1957
+ z20.union(allCredentialRequestFormats),
1958
+ credentialRequest,
1959
+ "Unable to validate format specific properties from credential request"
1960
+ ),
1961
+ credentialRequest,
1962
+ proofs
1963
+ };
1964
+ }
1965
+ return {
1966
+ credentialRequest,
1967
+ proofs
1968
+ };
1969
+ }
1970
+
1971
+ // src/formats/proof-type/attestation/attestation-proof-type.ts
1972
+ async function verifyCredentialRequestAttestationProof(options) {
1973
+ const verificationResult = await verifyKeyAttestationJwt({
1974
+ ...options,
1975
+ use: "proof_type.attestation"
1976
+ });
1977
+ return verificationResult;
1978
+ }
1979
+
1980
+ // src/Openid4vciIssuer.ts
1981
+ var Openid4vciIssuer = class {
1982
+ constructor(options) {
1983
+ this.options = options;
1984
+ }
1985
+ getCredentialIssuerMetadataDraft11(credentialIssuerMetadata) {
1986
+ return parseWithErrorHandling10(zCredentialIssuerMetadataWithDraft11, credentialIssuerMetadata);
1987
+ }
1988
+ getKnownCredentialConfigurationsSupported(credentialIssuerMetadata) {
1989
+ return extractKnownCredentialConfigurationSupportedFormats(
1990
+ credentialIssuerMetadata.credential_configurations_supported
1991
+ );
1992
+ }
1993
+ /**
1994
+ * Create issuer metadata and validates the structure is correct
1995
+ */
1996
+ createCredentialIssuerMetadata(credentialIssuerMetadata) {
1997
+ return parseWithErrorHandling10(
1998
+ zCredentialIssuerMetadata,
1999
+ credentialIssuerMetadata,
2000
+ "Error validating credential issuer metadata"
2001
+ );
2002
+ }
2003
+ async createCredentialOffer(options) {
2004
+ return createCredentialOffer({
2005
+ callbacks: this.options.callbacks,
2006
+ credentialConfigurationIds: options.credentialConfigurationIds,
2007
+ grants: options.grants,
2008
+ issuerMetadata: options.issuerMetadata,
2009
+ additionalPayload: options.additionalPayload,
2010
+ credentialOfferScheme: options.credentialOfferScheme,
2011
+ credentialOfferUri: options.credentialOfferUri
2012
+ });
2013
+ }
2014
+ /**
2015
+ * @throws Oauth2ServerErrorResponseError - if verification of the jwt failed. You can extract
2016
+ * the credential error response from this.
2017
+ */
2018
+ async verifyCredentialRequestJwtProof(options) {
2019
+ try {
2020
+ return await verifyCredentialRequestJwtProof({
2021
+ callbacks: this.options.callbacks,
2022
+ credentialIssuer: options.issuerMetadata.credentialIssuer.credential_issuer,
2023
+ expectedNonce: options.expectedNonce,
2024
+ nonceExpiresAt: options.nonceExpiresAt,
2025
+ jwt: options.jwt,
2026
+ clientId: options.clientId,
2027
+ now: options.now
2028
+ });
2029
+ } catch (error) {
2030
+ throw new Oauth2ServerErrorResponseError(
2031
+ {
2032
+ error: Oauth2ErrorCodes3.InvalidProof,
2033
+ error_description: (
2034
+ // TOOD: error should have a internalErrorMessage and a publicErrorMessage
2035
+ error instanceof Oauth2JwtVerificationError || error instanceof Openid4vciError ? error.message : "Invalid proof"
2036
+ )
2037
+ },
2038
+ {
2039
+ internalMessage: "Error verifying credential request proof jwt",
2040
+ cause: error
2041
+ }
2042
+ );
2043
+ }
2044
+ }
2045
+ /**
2046
+ * @throws Oauth2ServerErrorResponseError - if verification of the key attestation failed. You can extract
2047
+ * the credential error response from this.
2048
+ */
2049
+ async verifyCredentialRequestAttestationProof(options) {
2050
+ try {
2051
+ return await verifyCredentialRequestAttestationProof({
2052
+ callbacks: this.options.callbacks,
2053
+ expectedNonce: options.expectedNonce,
2054
+ keyAttestationJwt: options.keyAttestationJwt,
2055
+ nonceExpiresAt: options.nonceExpiresAt,
2056
+ now: options.now
2057
+ });
2058
+ } catch (error) {
2059
+ throw new Oauth2ServerErrorResponseError(
2060
+ {
2061
+ error: Oauth2ErrorCodes3.InvalidProof,
2062
+ error_description: (
2063
+ // TOOD: error should have a internalErrorMessage and a publicErrorMessage
2064
+ error instanceof Oauth2JwtVerificationError || error instanceof Openid4vciError ? error.message : "Invalid proof"
2065
+ )
2066
+ },
2067
+ {
2068
+ internalMessage: "Error verifying credential request proof attestation",
2069
+ cause: error
2070
+ }
2071
+ );
2072
+ }
2073
+ }
2074
+ /**
2075
+ * @throws Oauth2ServerErrorResponseError - when validation of the credential request fails
2076
+ * You can extract the credential error response from this.
2077
+ */
2078
+ parseCredentialRequest(options) {
2079
+ try {
2080
+ return parseCredentialRequest(options);
2081
+ } catch (error) {
2082
+ throw new Oauth2ServerErrorResponseError(
2083
+ {
2084
+ error: Oauth2ErrorCodes3.InvalidCredentialRequest,
2085
+ error_description: (
2086
+ // TODO: error should have a internalErrorMessage and a publicErrorMessage
2087
+ error instanceof ValidationError4 ? error.message : "Invalid request"
2088
+ )
2089
+ },
2090
+ {
2091
+ internalMessage: "Error verifying credential request proof jwt",
2092
+ cause: error
2093
+ }
2094
+ );
2095
+ }
2096
+ }
2097
+ /**
2098
+ * @throws ValidationError - when validation of the credential response fails
2099
+ */
2100
+ createCredentialResponse(options) {
2101
+ return createCredentialResponse(options);
2102
+ }
2103
+ /**
2104
+ * @throws ValidationError - when validation of the nonce response fails
2105
+ */
2106
+ createNonceResponse(options) {
2107
+ return createNonceResponse(options);
2108
+ }
2109
+ };
2110
+ export {
2111
+ AuthorizationFlow,
2112
+ Openid4vciClient,
2113
+ Openid4vciDraftVersion,
2114
+ Openid4vciError,
2115
+ Openid4vciIssuer,
2116
+ Openid4vciRetrieveCredentialsError,
2117
+ Openid4vciSendNotificationError,
2118
+ credentialsSupportedToCredentialConfigurationsSupported,
2119
+ extractScopesForCredentialConfigurationIds,
2120
+ getCredentialConfigurationsMatchingRequestFormat,
2121
+ getGlobalConfig2 as getGlobalConfig,
2122
+ setGlobalConfig
2123
+ };
2124
+ //# sourceMappingURL=index.mjs.map