@pagopa/io-wallet-oid4vci 1.4.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +4449 -419
- package/dist/index.d.ts +4449 -419
- package/dist/index.js +449 -217
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +402 -164
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -59,8 +59,14 @@ __export(index_exports, {
|
|
|
59
59
|
verifyAuthorizationResponseFormPostJWT: () => verifyAuthorizationResponseFormPostJWT,
|
|
60
60
|
verifyCredentialRequestJwtProof: () => verifyCredentialRequestJwtProof,
|
|
61
61
|
verifyKeyAttestationJwt: () => verifyKeyAttestationJwt,
|
|
62
|
+
zAuthorizationCodeGrantV1_3: () => zAuthorizationCodeGrantV1_3,
|
|
63
|
+
zAuthorizationCodeGrantV1_4: () => zAuthorizationCodeGrantV1_4,
|
|
62
64
|
zAuthorizationResponse: () => zAuthorizationResponse,
|
|
63
65
|
zCredentialObject: () => zCredentialObject,
|
|
66
|
+
zCredentialOfferGrantsV1_3: () => zCredentialOfferGrantsV1_3,
|
|
67
|
+
zCredentialOfferGrantsV1_4: () => zCredentialOfferGrantsV1_4,
|
|
68
|
+
zCredentialOfferV1_3: () => zCredentialOfferV1_3,
|
|
69
|
+
zCredentialOfferV1_4: () => zCredentialOfferV1_4,
|
|
64
70
|
zCredentialRequestV1_0: () => zCredentialRequestV1_0,
|
|
65
71
|
zCredentialRequestV1_3: () => zCredentialRequestV1_3,
|
|
66
72
|
zCredentialResponseEncryption: () => zCredentialResponseEncryption,
|
|
@@ -272,7 +278,8 @@ async function sendAuthorizationResponseAndExtractCode(options) {
|
|
|
272
278
|
}
|
|
273
279
|
|
|
274
280
|
// src/credential-offer/extract-grant-details.ts
|
|
275
|
-
|
|
281
|
+
var import_io_wallet_utils2 = require("@pagopa/io-wallet-utils");
|
|
282
|
+
function requireAuthorizationCodeGrant(credentialOffer) {
|
|
276
283
|
if (!credentialOffer.grants) {
|
|
277
284
|
throw new CredentialOfferError("No grants found in credential offer");
|
|
278
285
|
}
|
|
@@ -280,6 +287,10 @@ function extractGrantDetails(credentialOffer) {
|
|
|
280
287
|
if (!authCodeGrant) {
|
|
281
288
|
throw new CredentialOfferError("authorization_code grant not found");
|
|
282
289
|
}
|
|
290
|
+
return authCodeGrant;
|
|
291
|
+
}
|
|
292
|
+
function extractGrantDetailsV1_3(options) {
|
|
293
|
+
const authCodeGrant = requireAuthorizationCodeGrant(options.credentialOffer);
|
|
283
294
|
return {
|
|
284
295
|
authorizationCodeGrant: {
|
|
285
296
|
authorizationServer: authCodeGrant.authorization_server,
|
|
@@ -289,10 +300,37 @@ function extractGrantDetails(credentialOffer) {
|
|
|
289
300
|
grantType: "authorization_code"
|
|
290
301
|
};
|
|
291
302
|
}
|
|
303
|
+
function extractGrantDetailsV1_4(options) {
|
|
304
|
+
const authCodeGrant = requireAuthorizationCodeGrant(options.credentialOffer);
|
|
305
|
+
return {
|
|
306
|
+
authorizationCodeGrant: {
|
|
307
|
+
authorizationServer: authCodeGrant.authorization_server,
|
|
308
|
+
issuerState: authCodeGrant.issuer_state
|
|
309
|
+
},
|
|
310
|
+
grantType: "authorization_code"
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
var dispatchExtractGrantDetails = (0, import_io_wallet_utils2.createVersionDispatcher)({
|
|
314
|
+
[import_io_wallet_utils2.ItWalletSpecsVersion.V1_0]: () => {
|
|
315
|
+
throw new import_io_wallet_utils2.ItWalletSpecsVersionError(
|
|
316
|
+
"extractGrantDetails",
|
|
317
|
+
import_io_wallet_utils2.ItWalletSpecsVersion.V1_0,
|
|
318
|
+
[import_io_wallet_utils2.ItWalletSpecsVersion.V1_3, import_io_wallet_utils2.ItWalletSpecsVersion.V1_4]
|
|
319
|
+
);
|
|
320
|
+
},
|
|
321
|
+
[import_io_wallet_utils2.ItWalletSpecsVersion.V1_3]: (o) => extractGrantDetailsV1_3(o),
|
|
322
|
+
[import_io_wallet_utils2.ItWalletSpecsVersion.V1_4]: (o) => extractGrantDetailsV1_4(o)
|
|
323
|
+
});
|
|
324
|
+
function extractGrantDetails(options) {
|
|
325
|
+
return dispatchExtractGrantDetails(options);
|
|
326
|
+
}
|
|
292
327
|
|
|
293
328
|
// src/credential-offer/z-credential-offer.ts
|
|
329
|
+
var import_zod4 = require("zod");
|
|
330
|
+
|
|
331
|
+
// src/credential-offer/v1.3/z-credential-offer.ts
|
|
294
332
|
var import_zod2 = require("zod");
|
|
295
|
-
var
|
|
333
|
+
var zAuthorizationCodeGrantV1_3 = import_zod2.z.object({
|
|
296
334
|
/**
|
|
297
335
|
* CONDITIONALLY REQUIRED. HTTPS URL of the Authorization Server.
|
|
298
336
|
* REQUIRED only when the Credential Issuer uses multiple Authorization Servers.
|
|
@@ -310,14 +348,14 @@ var zAuthorizationCodeGrant = import_zod2.z.object({
|
|
|
310
348
|
*/
|
|
311
349
|
scope: import_zod2.z.string()
|
|
312
350
|
});
|
|
313
|
-
var
|
|
351
|
+
var zCredentialOfferGrantsV1_3 = import_zod2.z.object({
|
|
314
352
|
/**
|
|
315
353
|
* REQUIRED. Authorization Code grant details.
|
|
316
354
|
* IT-Wallet v1.3 only supports authorization_code grant.
|
|
317
355
|
*/
|
|
318
|
-
authorization_code:
|
|
356
|
+
authorization_code: zAuthorizationCodeGrantV1_3
|
|
319
357
|
});
|
|
320
|
-
var
|
|
358
|
+
var zCredentialOfferV1_3 = import_zod2.z.object({
|
|
321
359
|
/**
|
|
322
360
|
* REQUIRED. Array of credential configuration identifiers.
|
|
323
361
|
* References the types of credentials offered as defined in the Credential Issuer metadata.
|
|
@@ -332,24 +370,66 @@ var zCredentialOffer = import_zod2.z.object({
|
|
|
332
370
|
* REQUIRED. Grant information for the credential offer.
|
|
333
371
|
* IT-Wallet v1.3 requires authorization_code grant.
|
|
334
372
|
*/
|
|
335
|
-
grants:
|
|
373
|
+
grants: zCredentialOfferGrantsV1_3
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
// src/credential-offer/v1.4/z-credential-offer.ts
|
|
377
|
+
var import_zod3 = require("zod");
|
|
378
|
+
var zAuthorizationCodeGrantV1_4 = import_zod3.z.object({
|
|
379
|
+
/**
|
|
380
|
+
* CONDITIONALLY REQUIRED. HTTPS URL of the Authorization Server.
|
|
381
|
+
* REQUIRED only when the Credential Issuer uses multiple Authorization Servers.
|
|
382
|
+
* If present, MUST match one of the authorization_servers in the Credential Issuer metadata.
|
|
383
|
+
*/
|
|
384
|
+
authorization_server: import_zod3.z.url().optional(),
|
|
385
|
+
/**
|
|
386
|
+
* OPTIONAL. String value representing the issuer state.
|
|
387
|
+
* Used to correlate the authorization request with the credential offer.
|
|
388
|
+
*/
|
|
389
|
+
issuer_state: import_zod3.z.string().optional()
|
|
390
|
+
});
|
|
391
|
+
var zCredentialOfferGrantsV1_4 = import_zod3.z.object({
|
|
392
|
+
/**
|
|
393
|
+
* REQUIRED. Authorization Code grant details.
|
|
394
|
+
* IT-Wallet v1.4 only supports authorization_code grant.
|
|
395
|
+
*/
|
|
396
|
+
authorization_code: zAuthorizationCodeGrantV1_4
|
|
397
|
+
});
|
|
398
|
+
var zCredentialOfferV1_4 = import_zod3.z.object({
|
|
399
|
+
/**
|
|
400
|
+
* REQUIRED. Array of credential configuration identifiers.
|
|
401
|
+
* References the types of credentials offered as defined in the Credential Issuer metadata.
|
|
402
|
+
*/
|
|
403
|
+
credential_configuration_ids: import_zod3.z.array(import_zod3.z.string()).min(1),
|
|
404
|
+
/**
|
|
405
|
+
* REQUIRED. HTTPS URL of the Credential Issuer.
|
|
406
|
+
* The Credential Issuer from which the wallet will request credentials.
|
|
407
|
+
*/
|
|
408
|
+
credential_issuer: import_zod3.z.url(),
|
|
409
|
+
/**
|
|
410
|
+
* REQUIRED. Grant information for the credential offer.
|
|
411
|
+
* IT-Wallet v1.4 requires authorization_code grant.
|
|
412
|
+
*/
|
|
413
|
+
grants: zCredentialOfferGrantsV1_4
|
|
336
414
|
});
|
|
337
|
-
|
|
415
|
+
|
|
416
|
+
// src/credential-offer/z-credential-offer.ts
|
|
417
|
+
var zCredentialOfferUri = import_zod4.z.object({
|
|
338
418
|
/**
|
|
339
419
|
* OPTIONAL. Inline credential offer JSON (by value).
|
|
340
420
|
* URL-encoded JSON string containing the credential offer.
|
|
341
421
|
*/
|
|
342
|
-
credential_offer:
|
|
422
|
+
credential_offer: import_zod4.z.string().optional(),
|
|
343
423
|
/**
|
|
344
424
|
* OPTIONAL. URL pointing to the credential offer JSON (by reference).
|
|
345
425
|
* HTTPS URL where the credential offer can be fetched.
|
|
346
426
|
*/
|
|
347
|
-
credential_offer_uri:
|
|
427
|
+
credential_offer_uri: import_zod4.z.url().optional(),
|
|
348
428
|
/**
|
|
349
429
|
* URL scheme used for the credential offer.
|
|
350
430
|
* Determines the invocation method.
|
|
351
431
|
*/
|
|
352
|
-
scheme:
|
|
432
|
+
scheme: import_zod4.z.enum(["openid-credential-offer", "haip-vci", "https"])
|
|
353
433
|
}).refine((data) => data.credential_offer || data.credential_offer_uri, {
|
|
354
434
|
message: "Either credential_offer or credential_offer_uri must be present"
|
|
355
435
|
});
|
|
@@ -387,34 +467,48 @@ async function parseCredentialOfferUri(options) {
|
|
|
387
467
|
}
|
|
388
468
|
|
|
389
469
|
// src/credential-offer/resolve-credential-offer.ts
|
|
390
|
-
var
|
|
470
|
+
var import_io_wallet_utils3 = require("@pagopa/io-wallet-utils");
|
|
471
|
+
function parseCredentialOfferForVersion(config, data) {
|
|
472
|
+
switch (config.itWalletSpecsVersion) {
|
|
473
|
+
case import_io_wallet_utils3.ItWalletSpecsVersion.V1_3:
|
|
474
|
+
return zCredentialOfferV1_3.parse(data);
|
|
475
|
+
case import_io_wallet_utils3.ItWalletSpecsVersion.V1_4:
|
|
476
|
+
return zCredentialOfferV1_4.parse(data);
|
|
477
|
+
default:
|
|
478
|
+
throw new import_io_wallet_utils3.ItWalletSpecsVersionError(
|
|
479
|
+
"resolveCredentialOffer",
|
|
480
|
+
config.itWalletSpecsVersion,
|
|
481
|
+
[import_io_wallet_utils3.ItWalletSpecsVersion.V1_3, import_io_wallet_utils3.ItWalletSpecsVersion.V1_4]
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
391
485
|
async function resolveCredentialOffer(options) {
|
|
392
|
-
const { callbacks, credentialOffer } = options;
|
|
486
|
+
const { callbacks, config, credentialOffer } = options;
|
|
393
487
|
try {
|
|
394
488
|
if (credentialOffer.startsWith("openid-credential-offer://") || credentialOffer.startsWith("haip-vci://") || credentialOffer.startsWith("https://")) {
|
|
395
489
|
const parsed = await parseCredentialOfferUri({ uri: credentialOffer });
|
|
396
490
|
if (parsed.credential_offer) {
|
|
397
491
|
const decoded = decodeURIComponent(parsed.credential_offer);
|
|
398
492
|
const offerJson2 = JSON.parse(decoded);
|
|
399
|
-
return
|
|
493
|
+
return parseCredentialOfferForVersion(config, offerJson2);
|
|
400
494
|
}
|
|
401
495
|
if (parsed.credential_offer_uri) {
|
|
402
|
-
const fetch = (0,
|
|
496
|
+
const fetch = (0, import_io_wallet_utils3.createFetcher)(callbacks.fetch);
|
|
403
497
|
const response = await fetch(parsed.credential_offer_uri, {
|
|
404
498
|
headers: {
|
|
405
499
|
Accept: "application/json"
|
|
406
500
|
},
|
|
407
501
|
method: "GET"
|
|
408
502
|
});
|
|
409
|
-
await (0,
|
|
503
|
+
await (0, import_io_wallet_utils3.hasStatusOrThrow)(200, import_io_wallet_utils3.UnexpectedStatusCodeError)(response);
|
|
410
504
|
const offerJson2 = await response.json();
|
|
411
|
-
return
|
|
505
|
+
return parseCredentialOfferForVersion(config, offerJson2);
|
|
412
506
|
}
|
|
413
507
|
}
|
|
414
508
|
const offerJson = JSON.parse(credentialOffer);
|
|
415
|
-
return
|
|
509
|
+
return parseCredentialOfferForVersion(config, offerJson);
|
|
416
510
|
} catch (error) {
|
|
417
|
-
if (error instanceof CredentialOfferError || error instanceof
|
|
511
|
+
if (error instanceof CredentialOfferError || error instanceof import_io_wallet_utils3.UnexpectedStatusCodeError || error instanceof import_io_wallet_utils3.ItWalletSpecsVersionError) {
|
|
418
512
|
throw error;
|
|
419
513
|
}
|
|
420
514
|
throw new CredentialOfferError(
|
|
@@ -424,8 +518,34 @@ async function resolveCredentialOffer(options) {
|
|
|
424
518
|
}
|
|
425
519
|
|
|
426
520
|
// src/credential-offer/validate-credential-offer.ts
|
|
427
|
-
|
|
428
|
-
|
|
521
|
+
var import_io_wallet_utils4 = require("@pagopa/io-wallet-utils");
|
|
522
|
+
function assertAuthorizationServerAllowed(authorizationServer, authorizationServers) {
|
|
523
|
+
if (!authorizationServer) {
|
|
524
|
+
if (authorizationServers && authorizationServers.length > 1) {
|
|
525
|
+
throw new CredentialOfferError(
|
|
526
|
+
"authorization_server is REQUIRED when Credential Issuer uses multiple Authorization Servers"
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
if (!authorizationServers) {
|
|
532
|
+
throw new CredentialOfferError(
|
|
533
|
+
"credential offer specified an `authorization_server` but issuer metadata doesn't contain `authorization_servers`"
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
if (authorizationServers.length === 1) {
|
|
537
|
+
throw new CredentialOfferError(
|
|
538
|
+
"credential offer specified an `authorization_server` but issuer metadata's `authorization_servers` contains only an element"
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
if (!authorizationServers.includes(authorizationServer)) {
|
|
542
|
+
throw new CredentialOfferError(
|
|
543
|
+
`authorization_server '${authorizationServer}' does not match Credential Issuer metadata. Valid servers: ${authorizationServers.join(", ")}`
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
function validateBaseCredentialOffer(options) {
|
|
548
|
+
const { credentialIssuerMetadata, credentialOffer, versionLabel } = options;
|
|
429
549
|
if (!credentialOffer.credential_issuer.startsWith("https://")) {
|
|
430
550
|
throw new CredentialOfferError("credential_issuer must be an HTTPS URL");
|
|
431
551
|
}
|
|
@@ -435,53 +555,72 @@ async function validateCredentialOffer(options) {
|
|
|
435
555
|
);
|
|
436
556
|
}
|
|
437
557
|
if (!credentialOffer.grants) {
|
|
438
|
-
throw new CredentialOfferError(
|
|
558
|
+
throw new CredentialOfferError(
|
|
559
|
+
`grants is REQUIRED for IT-Wallet ${versionLabel}`
|
|
560
|
+
);
|
|
439
561
|
}
|
|
440
562
|
const authCodeGrant = credentialOffer.grants.authorization_code;
|
|
441
563
|
if (!authCodeGrant) {
|
|
442
564
|
throw new CredentialOfferError(
|
|
443
|
-
|
|
565
|
+
`authorization_code grant is REQUIRED for IT-Wallet ${versionLabel}`
|
|
444
566
|
);
|
|
445
567
|
}
|
|
446
|
-
|
|
568
|
+
assertAuthorizationServerAllowed(
|
|
569
|
+
authCodeGrant.authorization_server,
|
|
570
|
+
credentialIssuerMetadata?.authorization_servers
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
async function validateCredentialOfferV1_3(options) {
|
|
574
|
+
validateBaseCredentialOffer({
|
|
575
|
+
credentialIssuerMetadata: options.credentialIssuerMetadata,
|
|
576
|
+
credentialOffer: options.credentialOffer,
|
|
577
|
+
versionLabel: "v1.3"
|
|
578
|
+
});
|
|
579
|
+
if (!options.credentialOffer.grants.authorization_code.scope) {
|
|
447
580
|
throw new CredentialOfferError("authorization_code.scope is REQUIRED");
|
|
448
581
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
582
|
+
}
|
|
583
|
+
async function validateCredentialOfferV1_4(options) {
|
|
584
|
+
validateBaseCredentialOffer({
|
|
585
|
+
credentialIssuerMetadata: options.credentialIssuerMetadata,
|
|
586
|
+
credentialOffer: options.credentialOffer,
|
|
587
|
+
versionLabel: "v1.4"
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
var dispatchValidateCredentialOffer = (0, import_io_wallet_utils4.createVersionDispatcher)({
|
|
591
|
+
[import_io_wallet_utils4.ItWalletSpecsVersion.V1_0]: () => {
|
|
592
|
+
throw new import_io_wallet_utils4.ItWalletSpecsVersionError(
|
|
593
|
+
"validateCredentialOffer",
|
|
594
|
+
import_io_wallet_utils4.ItWalletSpecsVersion.V1_0,
|
|
595
|
+
[import_io_wallet_utils4.ItWalletSpecsVersion.V1_3, import_io_wallet_utils4.ItWalletSpecsVersion.V1_4]
|
|
596
|
+
);
|
|
597
|
+
},
|
|
598
|
+
[import_io_wallet_utils4.ItWalletSpecsVersion.V1_3]: (o) => validateCredentialOfferV1_3(o),
|
|
599
|
+
[import_io_wallet_utils4.ItWalletSpecsVersion.V1_4]: (o) => validateCredentialOfferV1_4(o)
|
|
600
|
+
});
|
|
601
|
+
async function validateCredentialOffer(options) {
|
|
602
|
+
return dispatchValidateCredentialOffer(options);
|
|
464
603
|
}
|
|
465
604
|
|
|
466
605
|
// src/credential-request/create-credential-request.ts
|
|
467
|
-
var
|
|
606
|
+
var import_io_wallet_utils7 = require("@pagopa/io-wallet-utils");
|
|
468
607
|
|
|
469
608
|
// src/credential-request/v1.0/create-credential-request.ts
|
|
470
|
-
var
|
|
609
|
+
var import_io_wallet_utils5 = require("@pagopa/io-wallet-utils");
|
|
471
610
|
|
|
472
611
|
// src/credential-request/v1.0/z-credential.ts
|
|
473
|
-
var
|
|
612
|
+
var import_zod6 = require("zod");
|
|
474
613
|
|
|
475
614
|
// src/credential-request/z-base-credential-request.ts
|
|
476
|
-
var
|
|
477
|
-
var zBaseCredentialRequest =
|
|
478
|
-
credential_configuration_id:
|
|
615
|
+
var import_zod5 = require("zod");
|
|
616
|
+
var zBaseCredentialRequest = import_zod5.z.object({
|
|
617
|
+
credential_configuration_id: import_zod5.z.string().optional().describe(
|
|
479
618
|
"REQUIRED if credential_identifier param is absent. MUST NOT be used otherwise."
|
|
480
619
|
),
|
|
481
|
-
credential_identifier:
|
|
620
|
+
credential_identifier: import_zod5.z.string().optional().describe(
|
|
482
621
|
"REQUIRED when Authorization Details of type openid_credential was returned. MUST NOT be used if credential_configuration_id is present."
|
|
483
622
|
),
|
|
484
|
-
transaction_id:
|
|
623
|
+
transaction_id: import_zod5.z.string().optional().describe(
|
|
485
624
|
"REQUIRED only in case of deferred flow. MUST NOT be present in immediate flow."
|
|
486
625
|
)
|
|
487
626
|
});
|
|
@@ -503,9 +642,9 @@ function credentialRequestRefiner(data, ctx) {
|
|
|
503
642
|
}
|
|
504
643
|
|
|
505
644
|
// src/credential-request/v1.0/z-credential.ts
|
|
506
|
-
var zCredentialRequestProof =
|
|
507
|
-
jwt:
|
|
508
|
-
proof_type:
|
|
645
|
+
var zCredentialRequestProof = import_zod6.z.object({
|
|
646
|
+
jwt: import_zod6.z.string().min(1, "JWT must not be empty"),
|
|
647
|
+
proof_type: import_zod6.z.literal("jwt")
|
|
509
648
|
// MUST be "jwt"
|
|
510
649
|
});
|
|
511
650
|
var zCredentialRequestV1_0 = zBaseCredentialRequest.extend({
|
|
@@ -528,12 +667,12 @@ var createCredentialRequest = async (options) => {
|
|
|
528
667
|
},
|
|
529
668
|
payload: {
|
|
530
669
|
aud: options.issuerIdentifier,
|
|
531
|
-
iat: (0,
|
|
670
|
+
iat: (0, import_io_wallet_utils5.dateToSeconds)(/* @__PURE__ */ new Date()),
|
|
532
671
|
iss: options.clientId,
|
|
533
672
|
nonce: options.nonce
|
|
534
673
|
}
|
|
535
674
|
});
|
|
536
|
-
return (0,
|
|
675
|
+
return (0, import_io_wallet_utils5.parseWithErrorHandling)(zCredentialRequestV1_0, {
|
|
537
676
|
credential_identifier: options.credential_identifier,
|
|
538
677
|
proof: {
|
|
539
678
|
jwt: proofJwt.jwt,
|
|
@@ -541,7 +680,7 @@ var createCredentialRequest = async (options) => {
|
|
|
541
680
|
}
|
|
542
681
|
});
|
|
543
682
|
} catch (error) {
|
|
544
|
-
if (error instanceof
|
|
683
|
+
if (error instanceof import_io_wallet_utils5.ValidationError) {
|
|
545
684
|
throw error;
|
|
546
685
|
}
|
|
547
686
|
throw new Oid4vciError(
|
|
@@ -552,13 +691,13 @@ var createCredentialRequest = async (options) => {
|
|
|
552
691
|
|
|
553
692
|
// src/credential-request/v1.3/create-credential-request.ts
|
|
554
693
|
var import_oauth22 = require("@openid4vc/oauth2");
|
|
555
|
-
var
|
|
694
|
+
var import_io_wallet_utils6 = require("@pagopa/io-wallet-utils");
|
|
556
695
|
|
|
557
696
|
// src/credential-request/v1.3/z-credential.ts
|
|
558
|
-
var
|
|
559
|
-
var zCredentialRequestProofJwt =
|
|
560
|
-
var zCredentialRequestProofs =
|
|
561
|
-
jwt:
|
|
697
|
+
var import_zod7 = require("zod");
|
|
698
|
+
var zCredentialRequestProofJwt = import_zod7.z.string().min(1, "JWT must not be empty in credential request proofs array");
|
|
699
|
+
var zCredentialRequestProofs = import_zod7.z.object({
|
|
700
|
+
jwt: import_zod7.z.tuple([zCredentialRequestProofJwt], zCredentialRequestProofJwt)
|
|
562
701
|
});
|
|
563
702
|
var zCredentialRequestV1_3 = zBaseCredentialRequest.extend({
|
|
564
703
|
proofs: zCredentialRequestProofs.describe(
|
|
@@ -574,16 +713,16 @@ var createCredentialRequest2 = async (options) => {
|
|
|
574
713
|
const { maxBatchSize, signers } = options;
|
|
575
714
|
const [firstSigner, ...otherSigners] = signers;
|
|
576
715
|
if (!firstSigner) {
|
|
577
|
-
throw new
|
|
716
|
+
throw new import_io_wallet_utils6.ValidationError("At least one signer is required");
|
|
578
717
|
}
|
|
579
718
|
if (maxBatchSize !== void 0) {
|
|
580
719
|
if (!Number.isInteger(maxBatchSize) || maxBatchSize <= 0) {
|
|
581
|
-
throw new
|
|
720
|
+
throw new import_io_wallet_utils6.ValidationError(
|
|
582
721
|
"Invalid maxBatchSize: it must be a positive integer"
|
|
583
722
|
);
|
|
584
723
|
}
|
|
585
724
|
if (signers.length > maxBatchSize) {
|
|
586
|
-
throw new
|
|
725
|
+
throw new import_io_wallet_utils6.ValidationError(
|
|
587
726
|
"The number of provided signers exceeds the maximum batch size allowed"
|
|
588
727
|
);
|
|
589
728
|
}
|
|
@@ -601,7 +740,7 @@ var createCredentialRequest2 = async (options) => {
|
|
|
601
740
|
);
|
|
602
741
|
const uniqueThumbprints = new Set(allThumbprints);
|
|
603
742
|
if (uniqueThumbprints.size !== allThumbprints.length) {
|
|
604
|
-
throw new
|
|
743
|
+
throw new import_io_wallet_utils6.ValidationError(
|
|
605
744
|
"Found multiple signers with the same JWK: each JWT proof must be unique and linked to a different credential key pair"
|
|
606
745
|
);
|
|
607
746
|
}
|
|
@@ -615,7 +754,7 @@ var createCredentialRequest2 = async (options) => {
|
|
|
615
754
|
},
|
|
616
755
|
payload: {
|
|
617
756
|
aud: options.issuerIdentifier,
|
|
618
|
-
iat: (0,
|
|
757
|
+
iat: (0, import_io_wallet_utils6.dateToSeconds)(/* @__PURE__ */ new Date()),
|
|
619
758
|
iss: options.clientId,
|
|
620
759
|
nonce: options.nonce
|
|
621
760
|
}
|
|
@@ -624,14 +763,14 @@ var createCredentialRequest2 = async (options) => {
|
|
|
624
763
|
createProofJwt(firstSigner),
|
|
625
764
|
...otherSigners.map(createProofJwt)
|
|
626
765
|
]);
|
|
627
|
-
return (0,
|
|
766
|
+
return (0, import_io_wallet_utils6.parseWithErrorHandling)(zCredentialRequestV1_3, {
|
|
628
767
|
credential_identifier: options.credential_identifier,
|
|
629
768
|
proofs: {
|
|
630
769
|
jwt: proofJwts
|
|
631
770
|
}
|
|
632
771
|
});
|
|
633
772
|
} catch (error) {
|
|
634
|
-
if (error instanceof
|
|
773
|
+
if (error instanceof import_io_wallet_utils6.ValidationError) {
|
|
635
774
|
throw error;
|
|
636
775
|
}
|
|
637
776
|
throw new Oid4vciError(
|
|
@@ -641,10 +780,10 @@ var createCredentialRequest2 = async (options) => {
|
|
|
641
780
|
};
|
|
642
781
|
|
|
643
782
|
// src/credential-request/create-credential-request.ts
|
|
644
|
-
var dispatchCreateCredentialRequest = (0,
|
|
645
|
-
[
|
|
646
|
-
[
|
|
647
|
-
[
|
|
783
|
+
var dispatchCreateCredentialRequest = (0, import_io_wallet_utils7.createVersionDispatcher)({
|
|
784
|
+
[import_io_wallet_utils7.ItWalletSpecsVersion.V1_0]: (o) => createCredentialRequest(o),
|
|
785
|
+
[import_io_wallet_utils7.ItWalletSpecsVersion.V1_3]: (o) => createCredentialRequest2(o),
|
|
786
|
+
[import_io_wallet_utils7.ItWalletSpecsVersion.V1_4]: (o) => (
|
|
648
787
|
// V1_4 reuses V1_3 credential request schema — no breaking changes between versions.
|
|
649
788
|
// Verified against compare/1.3.3...1.4.1: credential request parameters (format, proofs, key_attestation) identical.
|
|
650
789
|
createCredentialRequest2(o)
|
|
@@ -656,25 +795,25 @@ async function createCredentialRequest3(options) {
|
|
|
656
795
|
|
|
657
796
|
// src/credential-request/parse-credential-request.ts
|
|
658
797
|
var import_io_wallet_oauth23 = require("@pagopa/io-wallet-oauth2");
|
|
659
|
-
var
|
|
798
|
+
var import_io_wallet_utils8 = require("@pagopa/io-wallet-utils");
|
|
660
799
|
|
|
661
800
|
// src/credential-request/z-proof-jwt.ts
|
|
662
801
|
var import_io_wallet_oauth22 = require("@pagopa/io-wallet-oauth2");
|
|
663
|
-
var
|
|
664
|
-
var zBaseProofJwtHeader =
|
|
665
|
-
alg:
|
|
802
|
+
var import_zod8 = require("zod");
|
|
803
|
+
var zBaseProofJwtHeader = import_zod8.z.object({
|
|
804
|
+
alg: import_zod8.z.string().min(1),
|
|
666
805
|
jwk: import_io_wallet_oauth22.zJwk,
|
|
667
|
-
typ:
|
|
806
|
+
typ: import_zod8.z.literal("openid4vci-proof+jwt")
|
|
668
807
|
});
|
|
669
808
|
var zProofJwtHeaderV1_0 = zBaseProofJwtHeader.loose();
|
|
670
809
|
var zProofJwtHeaderV1_3 = zBaseProofJwtHeader.extend({
|
|
671
|
-
key_attestation:
|
|
810
|
+
key_attestation: import_zod8.z.string().min(1)
|
|
672
811
|
}).loose();
|
|
673
|
-
var zProofJwtPayload =
|
|
674
|
-
aud:
|
|
675
|
-
iat:
|
|
676
|
-
iss:
|
|
677
|
-
nonce:
|
|
812
|
+
var zProofJwtPayload = import_zod8.z.looseObject({
|
|
813
|
+
aud: import_zod8.z.string().min(1),
|
|
814
|
+
iat: import_zod8.z.number(),
|
|
815
|
+
iss: import_zod8.z.string().min(1).optional(),
|
|
816
|
+
nonce: import_zod8.z.string().min(1)
|
|
678
817
|
});
|
|
679
818
|
|
|
680
819
|
// src/credential-request/parse-credential-request.ts
|
|
@@ -683,12 +822,12 @@ function validateExpectedValues(credentialRequest, expected) {
|
|
|
683
822
|
return;
|
|
684
823
|
}
|
|
685
824
|
if (expected.credential_identifier && credentialRequest.credential_identifier !== expected.credential_identifier) {
|
|
686
|
-
throw new
|
|
825
|
+
throw new import_io_wallet_utils8.ValidationError(
|
|
687
826
|
"credential_identifier does not match expected value"
|
|
688
827
|
);
|
|
689
828
|
}
|
|
690
829
|
if (expected.credential_configuration_id && credentialRequest.credential_configuration_id !== expected.credential_configuration_id) {
|
|
691
|
-
throw new
|
|
830
|
+
throw new import_io_wallet_utils8.ValidationError(
|
|
692
831
|
"credential_configuration_id does not match expected value"
|
|
693
832
|
);
|
|
694
833
|
}
|
|
@@ -696,12 +835,12 @@ function validateExpectedValues(credentialRequest, expected) {
|
|
|
696
835
|
function validateTransactionContext(options) {
|
|
697
836
|
const { credentialRequest, isDeferredFlow } = options;
|
|
698
837
|
if (isDeferredFlow && !credentialRequest.transaction_id) {
|
|
699
|
-
throw new
|
|
838
|
+
throw new import_io_wallet_utils8.ValidationError(
|
|
700
839
|
"transaction_id is required for deferred credential issuance"
|
|
701
840
|
);
|
|
702
841
|
}
|
|
703
842
|
if (!isDeferredFlow && credentialRequest.transaction_id) {
|
|
704
|
-
throw new
|
|
843
|
+
throw new import_io_wallet_utils8.ValidationError(
|
|
705
844
|
"transaction_id must not be present in immediate credential issuance flow"
|
|
706
845
|
);
|
|
707
846
|
}
|
|
@@ -709,27 +848,27 @@ function validateTransactionContext(options) {
|
|
|
709
848
|
function validateProofPayloadSemantics(options) {
|
|
710
849
|
const { expected, grantType, payload } = options;
|
|
711
850
|
if (grantType === "authorization_code" && !payload.iss) {
|
|
712
|
-
throw new
|
|
851
|
+
throw new import_io_wallet_utils8.ValidationError(
|
|
713
852
|
"Credential proof JWT payload must include iss for authorization_code grant"
|
|
714
853
|
);
|
|
715
854
|
}
|
|
716
855
|
if (expected?.audience && payload.aud !== expected.audience) {
|
|
717
|
-
throw new
|
|
856
|
+
throw new import_io_wallet_utils8.ValidationError(
|
|
718
857
|
"Credential proof JWT aud does not match expected audience"
|
|
719
858
|
);
|
|
720
859
|
}
|
|
721
860
|
if (expected?.nonce && payload.nonce !== expected.nonce) {
|
|
722
|
-
throw new
|
|
861
|
+
throw new import_io_wallet_utils8.ValidationError(
|
|
723
862
|
"Credential proof JWT nonce does not match expected nonce"
|
|
724
863
|
);
|
|
725
864
|
}
|
|
726
865
|
if (expected?.issuer && payload.iss && payload.iss !== expected.issuer) {
|
|
727
|
-
throw new
|
|
866
|
+
throw new import_io_wallet_utils8.ValidationError(
|
|
728
867
|
"Credential proof JWT iss does not match expected issuer"
|
|
729
868
|
);
|
|
730
869
|
}
|
|
731
870
|
if (grantType === "authorization_code" && expected?.issuer && !payload.iss) {
|
|
732
|
-
throw new
|
|
871
|
+
throw new import_io_wallet_utils8.ValidationError(
|
|
733
872
|
"Credential proof JWT payload is missing expected issuer (iss)"
|
|
734
873
|
);
|
|
735
874
|
}
|
|
@@ -739,15 +878,15 @@ function parseProofJwt(options) {
|
|
|
739
878
|
errorMessagePrefix: "Error decoding credential request proof JWT:",
|
|
740
879
|
jwt: options.jwt
|
|
741
880
|
});
|
|
742
|
-
const headerValidation = options.itWalletSpecsVersion ===
|
|
881
|
+
const headerValidation = options.itWalletSpecsVersion === import_io_wallet_utils8.ItWalletSpecsVersion.V1_3 || options.itWalletSpecsVersion === import_io_wallet_utils8.ItWalletSpecsVersion.V1_4 ? zProofJwtHeaderV1_3.safeParse(decoded.header) : zProofJwtHeaderV1_0.safeParse(decoded.header);
|
|
743
882
|
if (!headerValidation.success) {
|
|
744
|
-
throw new
|
|
883
|
+
throw new import_io_wallet_utils8.ValidationError(
|
|
745
884
|
"Credential proof JWT header is invalid or missing required claims"
|
|
746
885
|
);
|
|
747
886
|
}
|
|
748
887
|
const payloadValidation = zProofJwtPayload.safeParse(decoded.payload);
|
|
749
888
|
if (!payloadValidation.success) {
|
|
750
|
-
throw new
|
|
889
|
+
throw new import_io_wallet_utils8.ValidationError(
|
|
751
890
|
"Credential proof JWT payload is invalid or missing required claims"
|
|
752
891
|
);
|
|
753
892
|
}
|
|
@@ -764,7 +903,27 @@ function parseProofJwt(options) {
|
|
|
764
903
|
proofType: "jwt"
|
|
765
904
|
};
|
|
766
905
|
}
|
|
767
|
-
function
|
|
906
|
+
async function validateProofJwkUniqueness(options) {
|
|
907
|
+
if (options.proofs.length <= 1) {
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
const thumbprints = await Promise.all(
|
|
911
|
+
options.proofs.map(
|
|
912
|
+
(proof) => (0, import_io_wallet_utils8.calculateJwkThumbprint)({
|
|
913
|
+
hashAlgorithm: import_io_wallet_utils8.HashAlgorithm.Sha256,
|
|
914
|
+
hashCallback: options.callbacks.hash,
|
|
915
|
+
jwk: proof.header.jwk
|
|
916
|
+
})
|
|
917
|
+
)
|
|
918
|
+
);
|
|
919
|
+
const uniqueThumbprints = new Set(thumbprints);
|
|
920
|
+
if (uniqueThumbprints.size !== thumbprints.length) {
|
|
921
|
+
throw new import_io_wallet_utils8.ValidationError(
|
|
922
|
+
"Credential request proofs must use unique jwk header values"
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
async function normalizeProofs(options) {
|
|
768
927
|
if ("proof" in options.credentialRequest) {
|
|
769
928
|
return [
|
|
770
929
|
parseProofJwt({
|
|
@@ -775,7 +934,7 @@ function normalizeProofs(options) {
|
|
|
775
934
|
})
|
|
776
935
|
];
|
|
777
936
|
}
|
|
778
|
-
|
|
937
|
+
const proofs = options.credentialRequest.proofs.jwt.map(
|
|
779
938
|
(jwt) => parseProofJwt({
|
|
780
939
|
expected: options.expected,
|
|
781
940
|
grantType: options.grantType,
|
|
@@ -783,14 +942,20 @@ function normalizeProofs(options) {
|
|
|
783
942
|
jwt
|
|
784
943
|
})
|
|
785
944
|
);
|
|
945
|
+
await validateProofJwkUniqueness({
|
|
946
|
+
callbacks: options.callbacks,
|
|
947
|
+
proofs
|
|
948
|
+
});
|
|
949
|
+
return proofs;
|
|
786
950
|
}
|
|
787
|
-
function toResult(options) {
|
|
951
|
+
async function toResult(options) {
|
|
788
952
|
validateExpectedValues(options.credentialRequest, options.expected);
|
|
789
953
|
validateTransactionContext({
|
|
790
954
|
credentialRequest: options.credentialRequest,
|
|
791
955
|
isDeferredFlow: options.isDeferredFlow
|
|
792
956
|
});
|
|
793
|
-
const proofs = normalizeProofs({
|
|
957
|
+
const proofs = await normalizeProofs({
|
|
958
|
+
callbacks: options.callbacks,
|
|
794
959
|
credentialRequest: options.credentialRequest,
|
|
795
960
|
expected: options.expected,
|
|
796
961
|
grantType: options.grantType,
|
|
@@ -813,7 +978,7 @@ function toResult(options) {
|
|
|
813
978
|
};
|
|
814
979
|
}
|
|
815
980
|
function parseAuthorizationHeader(headers) {
|
|
816
|
-
const authorizationHeader = headers.get(
|
|
981
|
+
const authorizationHeader = headers.get(import_io_wallet_utils8.HEADERS.AUTHORIZATION)?.trim();
|
|
817
982
|
if (!authorizationHeader) {
|
|
818
983
|
throw new CredentialAuthorizationHeaderError(
|
|
819
984
|
"Credential request is missing required 'Authorization' header with DPoP scheme"
|
|
@@ -842,66 +1007,69 @@ function parseDpopProof(headers) {
|
|
|
842
1007
|
return extracted.dpopJwt;
|
|
843
1008
|
}
|
|
844
1009
|
function parseCredentialRequestV1_0(options) {
|
|
845
|
-
const credentialRequest = (0,
|
|
1010
|
+
const credentialRequest = (0, import_io_wallet_utils8.parseWithErrorHandling)(
|
|
846
1011
|
zCredentialRequestV1_0,
|
|
847
1012
|
options.credentialRequest,
|
|
848
1013
|
"Invalid credential request format for ItWalletSpecsVersion 1.0"
|
|
849
1014
|
);
|
|
850
1015
|
return toResult({
|
|
851
1016
|
accessToken: options.accessToken,
|
|
1017
|
+
callbacks: options.callbacks,
|
|
852
1018
|
credentialRequest,
|
|
853
1019
|
dpopProof: options.dpopProof,
|
|
854
1020
|
expected: options.expected,
|
|
855
1021
|
grantType: options.grantType,
|
|
856
1022
|
isDeferredFlow: options.isDeferredFlow,
|
|
857
|
-
itWalletSpecsVersion:
|
|
1023
|
+
itWalletSpecsVersion: import_io_wallet_utils8.ItWalletSpecsVersion.V1_0
|
|
858
1024
|
});
|
|
859
1025
|
}
|
|
860
1026
|
function parseCredentialRequestV1_3(options) {
|
|
861
|
-
const credentialRequest = (0,
|
|
1027
|
+
const credentialRequest = (0, import_io_wallet_utils8.parseWithErrorHandling)(
|
|
862
1028
|
zCredentialRequestV1_3,
|
|
863
1029
|
options.credentialRequest,
|
|
864
1030
|
"Invalid credential request format for ItWalletSpecsVersion 1.3"
|
|
865
1031
|
);
|
|
866
1032
|
return toResult({
|
|
867
1033
|
accessToken: options.accessToken,
|
|
1034
|
+
callbacks: options.callbacks,
|
|
868
1035
|
credentialRequest,
|
|
869
1036
|
dpopProof: options.dpopProof,
|
|
870
1037
|
expected: options.expected,
|
|
871
1038
|
grantType: options.grantType,
|
|
872
1039
|
isDeferredFlow: options.isDeferredFlow,
|
|
873
|
-
itWalletSpecsVersion:
|
|
1040
|
+
itWalletSpecsVersion: import_io_wallet_utils8.ItWalletSpecsVersion.V1_3
|
|
874
1041
|
});
|
|
875
1042
|
}
|
|
876
1043
|
function parseCredentialRequestV1_4(options) {
|
|
877
|
-
const credentialRequest = (0,
|
|
1044
|
+
const credentialRequest = (0, import_io_wallet_utils8.parseWithErrorHandling)(
|
|
878
1045
|
zCredentialRequestV1_3,
|
|
879
1046
|
options.credentialRequest,
|
|
880
1047
|
"Invalid credential request format for ItWalletSpecsVersion 1.4"
|
|
881
1048
|
);
|
|
882
1049
|
return toResult({
|
|
883
1050
|
accessToken: options.accessToken,
|
|
1051
|
+
callbacks: options.callbacks,
|
|
884
1052
|
credentialRequest,
|
|
885
1053
|
dpopProof: options.dpopProof,
|
|
886
1054
|
expected: options.expected,
|
|
887
1055
|
grantType: options.grantType,
|
|
888
1056
|
isDeferredFlow: options.isDeferredFlow,
|
|
889
|
-
itWalletSpecsVersion:
|
|
1057
|
+
itWalletSpecsVersion: import_io_wallet_utils8.ItWalletSpecsVersion.V1_4
|
|
890
1058
|
// V1_4 reuses V1_3 proof schema
|
|
891
1059
|
});
|
|
892
1060
|
}
|
|
893
|
-
var dispatchParseCredentialRequest = (0,
|
|
894
|
-
[
|
|
895
|
-
[
|
|
896
|
-
[
|
|
1061
|
+
var dispatchParseCredentialRequest = (0, import_io_wallet_utils8.createVersionDispatcher)({
|
|
1062
|
+
[import_io_wallet_utils8.ItWalletSpecsVersion.V1_0]: parseCredentialRequestV1_0,
|
|
1063
|
+
[import_io_wallet_utils8.ItWalletSpecsVersion.V1_3]: parseCredentialRequestV1_3,
|
|
1064
|
+
[import_io_wallet_utils8.ItWalletSpecsVersion.V1_4]: parseCredentialRequestV1_4
|
|
897
1065
|
});
|
|
898
|
-
function parseCredentialRequest(options) {
|
|
1066
|
+
async function parseCredentialRequest(options) {
|
|
899
1067
|
const grantType = options.grantType ?? "authorization_code";
|
|
900
1068
|
const isDeferredFlow = options.isDeferredFlow ?? false;
|
|
901
1069
|
try {
|
|
902
1070
|
const accessToken = parseAuthorizationHeader(options.headers);
|
|
903
1071
|
const dpopProof = parseDpopProof(options.headers);
|
|
904
|
-
return dispatchParseCredentialRequest({
|
|
1072
|
+
return await dispatchParseCredentialRequest({
|
|
905
1073
|
...options,
|
|
906
1074
|
accessToken,
|
|
907
1075
|
dpopProof,
|
|
@@ -909,7 +1077,7 @@ function parseCredentialRequest(options) {
|
|
|
909
1077
|
isDeferredFlow
|
|
910
1078
|
});
|
|
911
1079
|
} catch (error) {
|
|
912
|
-
if (error instanceof
|
|
1080
|
+
if (error instanceof import_io_wallet_utils8.ItWalletSpecsVersionError || error instanceof import_io_wallet_oauth23.Oauth2JwtParseError || error instanceof import_io_wallet_utils8.ValidationError || error instanceof CredentialAuthorizationHeaderError || error instanceof MissingDpopProofError) {
|
|
913
1081
|
throw error;
|
|
914
1082
|
}
|
|
915
1083
|
throw new ParseCredentialRequestError(
|
|
@@ -922,44 +1090,44 @@ function parseCredentialRequest(options) {
|
|
|
922
1090
|
// src/credential-request/verify-credential-request-jwt-proof.ts
|
|
923
1091
|
var import_oauth24 = require("@openid4vc/oauth2");
|
|
924
1092
|
var import_io_wallet_oauth26 = require("@pagopa/io-wallet-oauth2");
|
|
925
|
-
var
|
|
1093
|
+
var import_io_wallet_utils11 = require("@pagopa/io-wallet-utils");
|
|
926
1094
|
|
|
927
1095
|
// src/credential-request/verify-key-attestation-jwt.ts
|
|
928
1096
|
var import_oauth23 = require("@openid4vc/oauth2");
|
|
929
1097
|
var import_io_wallet_oauth25 = require("@pagopa/io-wallet-oauth2");
|
|
930
|
-
var
|
|
1098
|
+
var import_io_wallet_utils10 = require("@pagopa/io-wallet-utils");
|
|
931
1099
|
|
|
932
1100
|
// src/wallet-provider/z-key-attestation.ts
|
|
933
1101
|
var import_io_wallet_oauth24 = require("@pagopa/io-wallet-oauth2");
|
|
934
1102
|
var import_io_wallet_oid_federation = require("@pagopa/io-wallet-oid-federation");
|
|
935
|
-
var
|
|
936
|
-
var
|
|
937
|
-
var zStatusList =
|
|
938
|
-
idx:
|
|
939
|
-
uri:
|
|
1103
|
+
var import_io_wallet_utils9 = require("@pagopa/io-wallet-utils");
|
|
1104
|
+
var import_zod9 = require("zod");
|
|
1105
|
+
var zStatusList = import_zod9.z.object({
|
|
1106
|
+
idx: import_zod9.z.number(),
|
|
1107
|
+
uri: import_zod9.z.url()
|
|
940
1108
|
});
|
|
941
|
-
var zKeyAttestationStatus =
|
|
1109
|
+
var zKeyAttestationStatus = import_zod9.z.object({
|
|
942
1110
|
status_list: zStatusList
|
|
943
1111
|
});
|
|
944
|
-
var zKeyAttestationAlg =
|
|
945
|
-
var zKeyAttestationHeader =
|
|
1112
|
+
var zKeyAttestationAlg = import_io_wallet_utils9.zItwSupportedSignatureAlg;
|
|
1113
|
+
var zKeyAttestationHeader = import_zod9.z.object({
|
|
946
1114
|
alg: zKeyAttestationAlg,
|
|
947
|
-
kid:
|
|
1115
|
+
kid: import_zod9.z.string(),
|
|
948
1116
|
trust_chain: import_io_wallet_oauth24.zTrustChain.optional(),
|
|
949
|
-
typ:
|
|
1117
|
+
typ: import_zod9.z.literal("key-attestation+jwt"),
|
|
950
1118
|
x5c: import_io_wallet_oauth24.zCertificateChain
|
|
951
1119
|
});
|
|
952
|
-
var zKeyAttestationPayload =
|
|
953
|
-
attested_keys:
|
|
954
|
-
certification:
|
|
955
|
-
exp:
|
|
956
|
-
iat:
|
|
957
|
-
iss:
|
|
958
|
-
key_storage:
|
|
1120
|
+
var zKeyAttestationPayload = import_zod9.z.object({
|
|
1121
|
+
attested_keys: import_zod9.z.array(import_io_wallet_oauth24.zJwk).nonempty(),
|
|
1122
|
+
certification: import_zod9.z.string().optional(),
|
|
1123
|
+
exp: import_zod9.z.number(),
|
|
1124
|
+
iat: import_zod9.z.number(),
|
|
1125
|
+
iss: import_zod9.z.string(),
|
|
1126
|
+
key_storage: import_zod9.z.array(import_io_wallet_oid_federation.zKeyStorageLevelV1_3).nonempty(),
|
|
959
1127
|
status: zKeyAttestationStatus,
|
|
960
|
-
user_authentication:
|
|
1128
|
+
user_authentication: import_zod9.z.array(import_io_wallet_oid_federation.zKeyStorageLevelV1_3).nonempty()
|
|
961
1129
|
});
|
|
962
|
-
var zKeyAttestationTypeHeader =
|
|
1130
|
+
var zKeyAttestationTypeHeader = import_zod9.z.literal("key-attestation+jwt");
|
|
963
1131
|
var keyAttestationTypeHeader = zKeyAttestationTypeHeader.value;
|
|
964
1132
|
|
|
965
1133
|
// src/credential-request/verify-key-attestation-jwt.ts
|
|
@@ -994,7 +1162,7 @@ async function verifyKeyAttestationJwt(options) {
|
|
|
994
1162
|
}
|
|
995
1163
|
return { header, payload, signer };
|
|
996
1164
|
} catch (error) {
|
|
997
|
-
if (error instanceof VerifyKeyAttestationJwtError || error instanceof
|
|
1165
|
+
if (error instanceof VerifyKeyAttestationJwtError || error instanceof import_io_wallet_utils10.ValidationError || error instanceof import_oauth23.Oauth2JwtParseError) {
|
|
998
1166
|
throw error;
|
|
999
1167
|
}
|
|
1000
1168
|
throw new VerifyKeyAttestationJwtError(
|
|
@@ -1024,7 +1192,7 @@ async function isJwkInSet(options) {
|
|
|
1024
1192
|
}
|
|
1025
1193
|
function verifyProofJwtIatOrThrow(options) {
|
|
1026
1194
|
try {
|
|
1027
|
-
(0,
|
|
1195
|
+
(0, import_io_wallet_utils11.verifyJwtIatOrThrow)({
|
|
1028
1196
|
iat: options.payload.iat,
|
|
1029
1197
|
now: options.now
|
|
1030
1198
|
});
|
|
@@ -1109,10 +1277,10 @@ async function verifyProofV1_3(options) {
|
|
|
1109
1277
|
}
|
|
1110
1278
|
return { header, keyAttestation: keyAttestationResult, payload, signer };
|
|
1111
1279
|
}
|
|
1112
|
-
var dispatchVerifyProof = (0,
|
|
1113
|
-
[
|
|
1114
|
-
[
|
|
1115
|
-
[
|
|
1280
|
+
var dispatchVerifyProof = (0, import_io_wallet_utils11.createVersionDispatcher)({
|
|
1281
|
+
[import_io_wallet_utils11.ItWalletSpecsVersion.V1_0]: (o) => verifyProofV1_0(o),
|
|
1282
|
+
[import_io_wallet_utils11.ItWalletSpecsVersion.V1_3]: (o) => verifyProofV1_3(o),
|
|
1283
|
+
[import_io_wallet_utils11.ItWalletSpecsVersion.V1_4]: (o) => verifyProofV1_3(o)
|
|
1116
1284
|
});
|
|
1117
1285
|
async function verifyCredentialRequestJwtProof(options) {
|
|
1118
1286
|
try {
|
|
@@ -1124,7 +1292,7 @@ async function verifyCredentialRequestJwtProof(options) {
|
|
|
1124
1292
|
}
|
|
1125
1293
|
return await dispatchVerifyProof({ ...options, now });
|
|
1126
1294
|
} catch (error) {
|
|
1127
|
-
if (error instanceof VerifyCredentialRequestJwtProofError || error instanceof VerifyKeyAttestationJwtError || error instanceof
|
|
1295
|
+
if (error instanceof VerifyCredentialRequestJwtProofError || error instanceof VerifyKeyAttestationJwtError || error instanceof import_io_wallet_utils11.ItWalletSpecsVersionError || error instanceof import_io_wallet_utils11.ValidationError || error instanceof import_io_wallet_oauth26.Oauth2JwtParseError) {
|
|
1128
1296
|
throw error;
|
|
1129
1297
|
}
|
|
1130
1298
|
throw new VerifyCredentialRequestJwtProofError(
|
|
@@ -1135,36 +1303,36 @@ async function verifyCredentialRequestJwtProof(options) {
|
|
|
1135
1303
|
}
|
|
1136
1304
|
|
|
1137
1305
|
// src/credential-response/create-credential-response.ts
|
|
1138
|
-
var
|
|
1306
|
+
var import_io_wallet_utils14 = require("@pagopa/io-wallet-utils");
|
|
1139
1307
|
|
|
1140
1308
|
// src/credential-response/v1.0/create-credential-response.ts
|
|
1141
|
-
var
|
|
1309
|
+
var import_io_wallet_utils12 = require("@pagopa/io-wallet-utils");
|
|
1142
1310
|
|
|
1143
1311
|
// src/credential-response/v1.0/z-credential-response.ts
|
|
1144
|
-
var
|
|
1312
|
+
var import_zod11 = require("zod");
|
|
1145
1313
|
|
|
1146
1314
|
// src/credential-response/z-immediate-credential-response.ts
|
|
1147
|
-
var
|
|
1148
|
-
var zCredentialObject =
|
|
1149
|
-
credential:
|
|
1315
|
+
var import_zod10 = require("zod");
|
|
1316
|
+
var zCredentialObject = import_zod10.z.object({
|
|
1317
|
+
credential: import_zod10.z.string()
|
|
1150
1318
|
});
|
|
1151
|
-
var zImmediateCredentialResponse =
|
|
1152
|
-
credentials:
|
|
1319
|
+
var zImmediateCredentialResponse = import_zod10.z.strictObject({
|
|
1320
|
+
credentials: import_zod10.z.array(zCredentialObject).nonempty().describe(
|
|
1153
1321
|
"Conditional. Array of issued Digital Credentials as JSON objects with `credential` member containing encoded credential string. Present for immediate issuance (HTTP 200)."
|
|
1154
1322
|
),
|
|
1155
|
-
notification_id:
|
|
1323
|
+
notification_id: import_zod10.z.string().optional().describe(
|
|
1156
1324
|
"OPTIONAL. Identifier for notification requests. Only present with credentials parameter."
|
|
1157
1325
|
)
|
|
1158
1326
|
});
|
|
1159
1327
|
|
|
1160
1328
|
// src/credential-response/v1.0/z-credential-response.ts
|
|
1161
|
-
var zDeferredCredentialResponseV1_0 =
|
|
1162
|
-
lead_time:
|
|
1329
|
+
var zDeferredCredentialResponseV1_0 = import_zod11.z.strictObject({
|
|
1330
|
+
lead_time: import_zod11.z.number().int().positive().describe(
|
|
1163
1331
|
"REQUIRED if credentials is not present, otherwise it MUST NOT be present. The amount of time (in seconds) required before making a Deferred Credential Request."
|
|
1164
1332
|
),
|
|
1165
|
-
transaction_id:
|
|
1333
|
+
transaction_id: import_zod11.z.string().nonempty()
|
|
1166
1334
|
});
|
|
1167
|
-
var zCredentialResponseV1_0 =
|
|
1335
|
+
var zCredentialResponseV1_0 = import_zod11.z.union([
|
|
1168
1336
|
zImmediateCredentialResponse,
|
|
1169
1337
|
zDeferredCredentialResponseV1_0
|
|
1170
1338
|
]);
|
|
@@ -1172,7 +1340,7 @@ var zCredentialResponseV1_0 = import_zod9.z.union([
|
|
|
1172
1340
|
// src/credential-response/v1.0/create-credential-response.ts
|
|
1173
1341
|
function createCredentialResponseV1_0(flow) {
|
|
1174
1342
|
if ("credentials" in flow) {
|
|
1175
|
-
return (0,
|
|
1343
|
+
return (0, import_io_wallet_utils12.parseWithErrorHandling)(
|
|
1176
1344
|
zCredentialResponseV1_0,
|
|
1177
1345
|
{
|
|
1178
1346
|
credentials: flow.credentials,
|
|
@@ -1183,7 +1351,7 @@ function createCredentialResponseV1_0(flow) {
|
|
|
1183
1351
|
"Invalid credential response for ItWalletSpecsVersion 1.0"
|
|
1184
1352
|
);
|
|
1185
1353
|
}
|
|
1186
|
-
return (0,
|
|
1354
|
+
return (0, import_io_wallet_utils12.parseWithErrorHandling)(
|
|
1187
1355
|
zCredentialResponseV1_0,
|
|
1188
1356
|
{
|
|
1189
1357
|
lead_time: flow.leadTime,
|
|
@@ -1194,17 +1362,17 @@ function createCredentialResponseV1_0(flow) {
|
|
|
1194
1362
|
}
|
|
1195
1363
|
|
|
1196
1364
|
// src/credential-response/v1.3/create-credential-response.ts
|
|
1197
|
-
var
|
|
1365
|
+
var import_io_wallet_utils13 = require("@pagopa/io-wallet-utils");
|
|
1198
1366
|
|
|
1199
1367
|
// src/credential-response/v1.3/z-credential-response.ts
|
|
1200
|
-
var
|
|
1201
|
-
var zDeferredCredentialResponseV1_3 =
|
|
1202
|
-
interval:
|
|
1368
|
+
var import_zod12 = require("zod");
|
|
1369
|
+
var zDeferredCredentialResponseV1_3 = import_zod12.z.strictObject({
|
|
1370
|
+
interval: import_zod12.z.number().int().positive().describe(
|
|
1203
1371
|
"REQUIRED if transaction_id is present, otherwise it MUST NOT be present. The amount of time (in seconds) required before making a Deferred Credential Request"
|
|
1204
1372
|
),
|
|
1205
|
-
transaction_id:
|
|
1373
|
+
transaction_id: import_zod12.z.string().nonempty()
|
|
1206
1374
|
});
|
|
1207
|
-
var zCredentialResponseV1_3 =
|
|
1375
|
+
var zCredentialResponseV1_3 = import_zod12.z.union([
|
|
1208
1376
|
zImmediateCredentialResponse,
|
|
1209
1377
|
zDeferredCredentialResponseV1_3
|
|
1210
1378
|
]);
|
|
@@ -1212,7 +1380,7 @@ var zCredentialResponseV1_3 = import_zod10.z.union([
|
|
|
1212
1380
|
// src/credential-response/v1.3/create-credential-response.ts
|
|
1213
1381
|
function createCredentialResponseV1_3(flow) {
|
|
1214
1382
|
if ("credentials" in flow) {
|
|
1215
|
-
return (0,
|
|
1383
|
+
return (0, import_io_wallet_utils13.parseWithErrorHandling)(
|
|
1216
1384
|
zCredentialResponseV1_3,
|
|
1217
1385
|
{
|
|
1218
1386
|
credentials: flow.credentials,
|
|
@@ -1223,7 +1391,7 @@ function createCredentialResponseV1_3(flow) {
|
|
|
1223
1391
|
"Invalid credential response for ItWalletSpecsVersion 1.3"
|
|
1224
1392
|
);
|
|
1225
1393
|
}
|
|
1226
|
-
return (0,
|
|
1394
|
+
return (0, import_io_wallet_utils13.parseWithErrorHandling)(
|
|
1227
1395
|
zCredentialResponseV1_3,
|
|
1228
1396
|
{
|
|
1229
1397
|
interval: flow.interval,
|
|
@@ -1234,14 +1402,14 @@ function createCredentialResponseV1_3(flow) {
|
|
|
1234
1402
|
}
|
|
1235
1403
|
|
|
1236
1404
|
// src/credential-response/create-credential-response.ts
|
|
1237
|
-
var dispatchBuildVersionedResponse = (0,
|
|
1238
|
-
[
|
|
1405
|
+
var dispatchBuildVersionedResponse = (0, import_io_wallet_utils14.createVersionDispatcher)({
|
|
1406
|
+
[import_io_wallet_utils14.ItWalletSpecsVersion.V1_0]: (o) => createCredentialResponseV1_0(
|
|
1239
1407
|
o.flow
|
|
1240
1408
|
),
|
|
1241
|
-
[
|
|
1409
|
+
[import_io_wallet_utils14.ItWalletSpecsVersion.V1_3]: (o) => createCredentialResponseV1_3(
|
|
1242
1410
|
o.flow
|
|
1243
1411
|
),
|
|
1244
|
-
[
|
|
1412
|
+
[import_io_wallet_utils14.ItWalletSpecsVersion.V1_4]: (o) => createCredentialResponseV1_3(
|
|
1245
1413
|
o.flow
|
|
1246
1414
|
// V1_4 reuses V1_3 credential response schema — no breaking changes between versions.
|
|
1247
1415
|
// Verified against compare/1.3.3...1.4.1: credential response parameters identical.
|
|
@@ -1266,7 +1434,7 @@ async function createCredentialResponse(options) {
|
|
|
1266
1434
|
}
|
|
1267
1435
|
return { credentialResponse, credentialResponseJwt };
|
|
1268
1436
|
} catch (error) {
|
|
1269
|
-
if (error instanceof
|
|
1437
|
+
if (error instanceof import_io_wallet_utils14.ValidationError || error instanceof Oid4vciError) {
|
|
1270
1438
|
throw error;
|
|
1271
1439
|
}
|
|
1272
1440
|
throw new CreateCredentialResponseError(
|
|
@@ -1290,49 +1458,49 @@ async function encryptResponse(credentialResponse, credentialResponseEncryption,
|
|
|
1290
1458
|
}
|
|
1291
1459
|
|
|
1292
1460
|
// src/credential-response/fetch-credential-response.ts
|
|
1293
|
-
var
|
|
1461
|
+
var import_io_wallet_utils15 = require("@pagopa/io-wallet-utils");
|
|
1294
1462
|
|
|
1295
1463
|
// src/credential-response/z-credential-response.ts
|
|
1296
1464
|
var import_io_wallet_oauth27 = require("@pagopa/io-wallet-oauth2");
|
|
1297
|
-
var
|
|
1298
|
-
var zCredentialResponseEncryption =
|
|
1465
|
+
var import_zod13 = require("zod");
|
|
1466
|
+
var zCredentialResponseEncryption = import_zod13.z.looseObject({
|
|
1299
1467
|
alg: import_io_wallet_oauth27.zAlgValueNotNone,
|
|
1300
|
-
enc:
|
|
1468
|
+
enc: import_zod13.z.string(),
|
|
1301
1469
|
jwk: import_io_wallet_oauth27.zJwk
|
|
1302
1470
|
});
|
|
1303
1471
|
|
|
1304
1472
|
// src/credential-response/fetch-credential-response.ts
|
|
1305
1473
|
async function fetchCredentialResponse(options) {
|
|
1306
1474
|
try {
|
|
1307
|
-
const fetch = (0,
|
|
1475
|
+
const fetch = (0, import_io_wallet_utils15.createFetcher)(options.callbacks.fetch);
|
|
1308
1476
|
const credentialResponse = await fetch(options.credentialEndpoint, {
|
|
1309
1477
|
body: JSON.stringify(options.credentialRequest),
|
|
1310
1478
|
headers: {
|
|
1311
|
-
[
|
|
1312
|
-
[
|
|
1313
|
-
[
|
|
1479
|
+
[import_io_wallet_utils15.HEADERS.AUTHORIZATION]: `DPoP ${options.accessToken}`,
|
|
1480
|
+
[import_io_wallet_utils15.HEADERS.CONTENT_TYPE]: import_io_wallet_utils15.CONTENT_TYPES.JSON,
|
|
1481
|
+
[import_io_wallet_utils15.HEADERS.DPOP]: options.dPoP
|
|
1314
1482
|
},
|
|
1315
1483
|
method: "POST"
|
|
1316
1484
|
});
|
|
1317
|
-
await (0,
|
|
1485
|
+
await (0, import_io_wallet_utils15.hasStatusOrThrow)(
|
|
1318
1486
|
[200, 202],
|
|
1319
|
-
|
|
1487
|
+
import_io_wallet_utils15.UnexpectedStatusCodeError
|
|
1320
1488
|
)(credentialResponse);
|
|
1321
1489
|
const credentialResponseJson = await credentialResponse.json();
|
|
1322
1490
|
if ("proof" in options.credentialRequest) {
|
|
1323
|
-
return (0,
|
|
1491
|
+
return (0, import_io_wallet_utils15.parseWithErrorHandling)(
|
|
1324
1492
|
zCredentialResponseV1_0,
|
|
1325
1493
|
credentialResponseJson,
|
|
1326
1494
|
`Failed to parse credential response (v1.0)`
|
|
1327
1495
|
);
|
|
1328
1496
|
}
|
|
1329
|
-
return (0,
|
|
1497
|
+
return (0, import_io_wallet_utils15.parseWithErrorHandling)(
|
|
1330
1498
|
zCredentialResponseV1_3,
|
|
1331
1499
|
credentialResponseJson,
|
|
1332
1500
|
`Failed to parse credential response (v1.3)`
|
|
1333
1501
|
);
|
|
1334
1502
|
} catch (error) {
|
|
1335
|
-
if (error instanceof
|
|
1503
|
+
if (error instanceof import_io_wallet_utils15.UnexpectedStatusCodeError || error instanceof import_io_wallet_utils15.ValidationError) {
|
|
1336
1504
|
throw error;
|
|
1337
1505
|
}
|
|
1338
1506
|
throw new FetchCredentialResponseError(
|
|
@@ -1344,28 +1512,34 @@ async function fetchCredentialResponse(options) {
|
|
|
1344
1512
|
// src/metadata/fetch-metadata.ts
|
|
1345
1513
|
var import_io_wallet_oauth28 = require("@pagopa/io-wallet-oauth2");
|
|
1346
1514
|
var import_io_wallet_oid_federation3 = require("@pagopa/io-wallet-oid-federation");
|
|
1347
|
-
var
|
|
1348
|
-
var
|
|
1515
|
+
var import_io_wallet_utils16 = require("@pagopa/io-wallet-utils");
|
|
1516
|
+
var import_zod15 = __toESM(require("zod"));
|
|
1349
1517
|
|
|
1350
1518
|
// src/metadata/z-metadata-response.ts
|
|
1351
1519
|
var import_io_wallet_oid_federation2 = require("@pagopa/io-wallet-oid-federation");
|
|
1352
|
-
var
|
|
1353
|
-
var zMetadataResponseV1_0 =
|
|
1354
|
-
discoveredVia:
|
|
1520
|
+
var import_zod14 = require("zod");
|
|
1521
|
+
var zMetadataResponseV1_0 = import_zod14.z.object({
|
|
1522
|
+
discoveredVia: import_zod14.z.enum(["federation"]),
|
|
1355
1523
|
metadata: import_io_wallet_oid_federation2.itWalletMetadataV1_0,
|
|
1356
1524
|
openid_federation_claims: import_io_wallet_oid_federation2.itWalletEntityStatementClaimsSchema
|
|
1357
1525
|
});
|
|
1358
|
-
var zMetadataResponseV1_3 =
|
|
1359
|
-
|
|
1526
|
+
var zMetadataResponseV1_3 = import_zod14.z.object({
|
|
1527
|
+
/**
|
|
1528
|
+
* Entity statement claims of the Authorization Server, present only when the
|
|
1529
|
+
* selected authorization server was resolved through a federation entity
|
|
1530
|
+
* distinct from the Credential Issuer.
|
|
1531
|
+
*/
|
|
1532
|
+
authorization_server_federation_claims: import_io_wallet_oid_federation2.itWalletEntityStatementClaimsSchema.optional(),
|
|
1533
|
+
discoveredVia: import_zod14.z.enum(["federation", "oid4vci"]),
|
|
1360
1534
|
metadata: import_io_wallet_oid_federation2.itWalletMetadataV1_3,
|
|
1361
1535
|
openid_federation_claims: import_io_wallet_oid_federation2.itWalletEntityStatementClaimsSchema.optional()
|
|
1362
1536
|
});
|
|
1363
|
-
var zMetadataResponse =
|
|
1537
|
+
var zMetadataResponse = import_zod14.z.union([
|
|
1364
1538
|
zMetadataResponseV1_0,
|
|
1365
1539
|
zMetadataResponseV1_3
|
|
1366
1540
|
]);
|
|
1367
|
-
var zPartialIssuerMetadata =
|
|
1368
|
-
authorization_servers:
|
|
1541
|
+
var zPartialIssuerMetadata = import_zod14.z.looseObject({
|
|
1542
|
+
authorization_servers: import_zod14.z.tuple([import_zod14.z.url()], import_zod14.z.url()).optional()
|
|
1369
1543
|
});
|
|
1370
1544
|
|
|
1371
1545
|
// src/metadata/fetch-metadata.ts
|
|
@@ -1400,7 +1574,7 @@ async function tryFederationDiscovery(fetch, baseUrl, verifyJwt4) {
|
|
|
1400
1574
|
payload
|
|
1401
1575
|
});
|
|
1402
1576
|
if (!result.verified) {
|
|
1403
|
-
throw new
|
|
1577
|
+
throw new import_io_wallet_utils16.ValidationError(
|
|
1404
1578
|
"Entity statement signature verification failed"
|
|
1405
1579
|
);
|
|
1406
1580
|
}
|
|
@@ -1411,31 +1585,74 @@ async function tryFederationDiscovery(fetch, baseUrl, verifyJwt4) {
|
|
|
1411
1585
|
openid_federation_claims: payload
|
|
1412
1586
|
};
|
|
1413
1587
|
} catch (error) {
|
|
1414
|
-
if (error instanceof
|
|
1588
|
+
if (error instanceof import_io_wallet_utils16.ValidationError) {
|
|
1415
1589
|
throw error;
|
|
1416
1590
|
}
|
|
1417
1591
|
return void 0;
|
|
1418
1592
|
}
|
|
1419
1593
|
}
|
|
1420
|
-
async function
|
|
1594
|
+
async function applyFederationAuthorizationServerSelection(fetch, federationResult, authorizationServer, verifyJwt4) {
|
|
1595
|
+
const credentialIssuer = federationResult.metadata?.openid_credential_issuer?.credential_issuer;
|
|
1596
|
+
const authorizationServers = federationResult.metadata?.openid_credential_issuer?.authorization_servers;
|
|
1597
|
+
let selectedAuthorizationServer;
|
|
1598
|
+
if (authorizationServer) {
|
|
1599
|
+
assertAuthorizationServerAllowed(authorizationServer, authorizationServers);
|
|
1600
|
+
selectedAuthorizationServer = authorizationServer;
|
|
1601
|
+
} else if (authorizationServers && authorizationServers.length > 0) {
|
|
1602
|
+
selectedAuthorizationServer = credentialIssuer && authorizationServers.includes(credentialIssuer) ? credentialIssuer : authorizationServers[0];
|
|
1603
|
+
} else {
|
|
1604
|
+
selectedAuthorizationServer = credentialIssuer;
|
|
1605
|
+
}
|
|
1606
|
+
if (!selectedAuthorizationServer || selectedAuthorizationServer === credentialIssuer) {
|
|
1607
|
+
return federationResult;
|
|
1608
|
+
}
|
|
1609
|
+
const parsedSelectedAuthorizationServer = import_zod15.default.url().safeParse(selectedAuthorizationServer);
|
|
1610
|
+
if (!parsedSelectedAuthorizationServer.success || !parsedSelectedAuthorizationServer.data.startsWith("https://")) {
|
|
1611
|
+
throw new import_io_wallet_utils16.ValidationError(
|
|
1612
|
+
"selected authorization server is not a valid HTTPS URL"
|
|
1613
|
+
);
|
|
1614
|
+
}
|
|
1615
|
+
const authorizationServerResult = await tryFederationDiscovery(
|
|
1616
|
+
fetch,
|
|
1617
|
+
parsedSelectedAuthorizationServer.data,
|
|
1618
|
+
verifyJwt4
|
|
1619
|
+
);
|
|
1620
|
+
const resolvedAuthorizationServer = authorizationServerResult?.metadata?.oauth_authorization_server;
|
|
1621
|
+
if (!resolvedAuthorizationServer) {
|
|
1622
|
+
throw new import_io_wallet_utils16.ValidationError(
|
|
1623
|
+
`Federation discovery did not yield oauth_authorization_server metadata for authorization server '${selectedAuthorizationServer}'`
|
|
1624
|
+
);
|
|
1625
|
+
}
|
|
1626
|
+
return {
|
|
1627
|
+
...federationResult,
|
|
1628
|
+
authorization_server_federation_claims: authorizationServerResult.openid_federation_claims,
|
|
1629
|
+
metadata: {
|
|
1630
|
+
...federationResult.metadata,
|
|
1631
|
+
oauth_authorization_server: resolvedAuthorizationServer
|
|
1632
|
+
}
|
|
1633
|
+
};
|
|
1634
|
+
}
|
|
1635
|
+
async function fallbackDiscovery(fetch, baseUrl, authorizationServer) {
|
|
1421
1636
|
const issuerUrl = new URL(
|
|
1422
1637
|
".well-known/openid-credential-issuer",
|
|
1423
1638
|
ensureTrailingSlash(baseUrl)
|
|
1424
1639
|
).toString();
|
|
1425
1640
|
const issuerResponse = await fetch(issuerUrl);
|
|
1426
|
-
await (0,
|
|
1427
|
-
const issuerJson = (0,
|
|
1641
|
+
await (0, import_io_wallet_utils16.hasStatusOrThrow)(200, import_io_wallet_utils16.UnexpectedStatusCodeError)(issuerResponse);
|
|
1642
|
+
const issuerJson = (0, import_io_wallet_utils16.parseWithErrorHandling)(
|
|
1428
1643
|
zPartialIssuerMetadata,
|
|
1429
1644
|
await issuerResponse.json(),
|
|
1430
1645
|
"Failed to parse credential issuer metadata"
|
|
1431
1646
|
);
|
|
1432
1647
|
const authorizationServers = issuerJson.authorization_servers;
|
|
1648
|
+
assertAuthorizationServerAllowed(authorizationServer, authorizationServers);
|
|
1433
1649
|
let oauthAuthorizationServer;
|
|
1434
1650
|
if (authorizationServers && authorizationServers.length > 0) {
|
|
1435
|
-
const
|
|
1651
|
+
const selectedAuthorizationServer = authorizationServer ?? authorizationServers[0];
|
|
1652
|
+
const parsedUrl = import_zod15.default.url().safeParse(selectedAuthorizationServer);
|
|
1436
1653
|
if (!parsedUrl.success || !parsedUrl.data.startsWith("https://")) {
|
|
1437
|
-
throw new
|
|
1438
|
-
"
|
|
1654
|
+
throw new import_io_wallet_utils16.ValidationError(
|
|
1655
|
+
"selected authorization server is not a valid HTTPS URL"
|
|
1439
1656
|
);
|
|
1440
1657
|
}
|
|
1441
1658
|
const authServerUrl = new URL(
|
|
@@ -1443,7 +1660,7 @@ async function fallbackDiscovery(fetch, baseUrl) {
|
|
|
1443
1660
|
ensureTrailingSlash(parsedUrl.data)
|
|
1444
1661
|
).toString();
|
|
1445
1662
|
const authServerResponse = await fetch(authServerUrl);
|
|
1446
|
-
await (0,
|
|
1663
|
+
await (0, import_io_wallet_utils16.hasStatusOrThrow)(200, import_io_wallet_utils16.UnexpectedStatusCodeError)(authServerResponse);
|
|
1447
1664
|
oauthAuthorizationServer = await authServerResponse.json();
|
|
1448
1665
|
} else {
|
|
1449
1666
|
oauthAuthorizationServer = issuerJson;
|
|
@@ -1457,7 +1674,7 @@ async function fallbackDiscovery(fetch, baseUrl) {
|
|
|
1457
1674
|
};
|
|
1458
1675
|
}
|
|
1459
1676
|
async function fetchMetadataV1_0(options) {
|
|
1460
|
-
const fetch = (0,
|
|
1677
|
+
const fetch = (0, import_io_wallet_utils16.createFetcher)(options.callbacks.fetch);
|
|
1461
1678
|
const federationResult = await tryFederationDiscovery(
|
|
1462
1679
|
fetch,
|
|
1463
1680
|
options.credentialIssuerUrl,
|
|
@@ -1468,43 +1685,52 @@ async function fetchMetadataV1_0(options) {
|
|
|
1468
1685
|
`Federation discovery failed for IT Wallet v1.0; no fallback available for credentialIssuerUrl ${options.credentialIssuerUrl}`
|
|
1469
1686
|
);
|
|
1470
1687
|
}
|
|
1471
|
-
return (0,
|
|
1688
|
+
return (0, import_io_wallet_utils16.parseWithErrorHandling)(
|
|
1472
1689
|
zMetadataResponseV1_0,
|
|
1473
1690
|
federationResult,
|
|
1474
1691
|
"Failed to parse v1.0 metadata response"
|
|
1475
1692
|
);
|
|
1476
1693
|
}
|
|
1477
1694
|
async function fetchMetadataV1_3(options) {
|
|
1478
|
-
const fetch = (0,
|
|
1695
|
+
const fetch = (0, import_io_wallet_utils16.createFetcher)(options.callbacks.fetch);
|
|
1479
1696
|
const federationResult = await tryFederationDiscovery(
|
|
1480
1697
|
fetch,
|
|
1481
1698
|
options.credentialIssuerUrl,
|
|
1482
1699
|
options.callbacks.verifyJwt
|
|
1483
1700
|
);
|
|
1484
|
-
const raw = federationResult
|
|
1485
|
-
|
|
1701
|
+
const raw = federationResult ? await applyFederationAuthorizationServerSelection(
|
|
1702
|
+
fetch,
|
|
1703
|
+
federationResult,
|
|
1704
|
+
options.authorizationServer,
|
|
1705
|
+
options.callbacks.verifyJwt
|
|
1706
|
+
) : await fallbackDiscovery(
|
|
1707
|
+
fetch,
|
|
1708
|
+
options.credentialIssuerUrl,
|
|
1709
|
+
options.authorizationServer
|
|
1710
|
+
);
|
|
1711
|
+
return (0, import_io_wallet_utils16.parseWithErrorHandling)(
|
|
1486
1712
|
zMetadataResponseV1_3,
|
|
1487
1713
|
raw,
|
|
1488
1714
|
"Failed to parse v1.3 metadata response"
|
|
1489
1715
|
);
|
|
1490
1716
|
}
|
|
1491
|
-
var dispatchFetchMetadata = (0,
|
|
1492
|
-
[
|
|
1493
|
-
[
|
|
1717
|
+
var dispatchFetchMetadata = (0, import_io_wallet_utils16.createVersionDispatcher)({
|
|
1718
|
+
[import_io_wallet_utils16.ItWalletSpecsVersion.V1_0]: (o) => fetchMetadataV1_0(o),
|
|
1719
|
+
[import_io_wallet_utils16.ItWalletSpecsVersion.V1_3]: (o) => fetchMetadataV1_3(o),
|
|
1494
1720
|
// V1_4 reuses V1_3 metadata schema — no breaking changes between versions.
|
|
1495
|
-
[
|
|
1721
|
+
[import_io_wallet_utils16.ItWalletSpecsVersion.V1_4]: (o) => fetchMetadataV1_3(o)
|
|
1496
1722
|
});
|
|
1497
1723
|
async function fetchMetadata(options) {
|
|
1498
1724
|
try {
|
|
1499
|
-
const urlValidation =
|
|
1725
|
+
const urlValidation = import_zod15.default.url().safeParse(options.credentialIssuerUrl);
|
|
1500
1726
|
if (!urlValidation.success || !urlValidation.data.startsWith("https://")) {
|
|
1501
|
-
throw new
|
|
1727
|
+
throw new import_io_wallet_utils16.ValidationError(
|
|
1502
1728
|
"credentialIssuerUrl must be a valid HTTPS URL"
|
|
1503
1729
|
);
|
|
1504
1730
|
}
|
|
1505
1731
|
return await dispatchFetchMetadata(options);
|
|
1506
1732
|
} catch (error) {
|
|
1507
|
-
if (error instanceof
|
|
1733
|
+
if (error instanceof import_io_wallet_utils16.UnexpectedStatusCodeError || error instanceof import_io_wallet_utils16.ValidationError || error instanceof import_io_wallet_utils16.ItWalletSpecsVersionError || error instanceof CredentialOfferError || error instanceof FetchMetadataError) {
|
|
1508
1734
|
throw error;
|
|
1509
1735
|
}
|
|
1510
1736
|
throw new FetchMetadataError("Unexpected error during metadata fetch", {
|
|
@@ -1515,7 +1741,7 @@ async function fetchMetadata(options) {
|
|
|
1515
1741
|
|
|
1516
1742
|
// src/wallet-provider/WalletProvider.ts
|
|
1517
1743
|
var import_io_wallet_oauth29 = require("@pagopa/io-wallet-oauth2");
|
|
1518
|
-
var
|
|
1744
|
+
var import_io_wallet_utils17 = require("@pagopa/io-wallet-utils");
|
|
1519
1745
|
function assertV1_0Options(options) {
|
|
1520
1746
|
if (options.signer.method !== "federation") {
|
|
1521
1747
|
throw new WalletProviderError(
|
|
@@ -1578,7 +1804,7 @@ var WalletProvider = class {
|
|
|
1578
1804
|
const { signJwt } = options.callbacks;
|
|
1579
1805
|
const now = /* @__PURE__ */ new Date();
|
|
1580
1806
|
const issuedAt = options.issuedAt ?? now;
|
|
1581
|
-
const expiresAt = options.expiresAt ?? (0,
|
|
1807
|
+
const expiresAt = options.expiresAt ?? (0, import_io_wallet_utils17.addSecondsToDate)(now, 3600 * 24 * 360);
|
|
1582
1808
|
const header = {
|
|
1583
1809
|
alg: options.signer.alg,
|
|
1584
1810
|
kid: options.signer.kid,
|
|
@@ -1588,8 +1814,8 @@ var WalletProvider = class {
|
|
|
1588
1814
|
};
|
|
1589
1815
|
const payload = {
|
|
1590
1816
|
attested_keys: options.attestedKeys,
|
|
1591
|
-
exp: (0,
|
|
1592
|
-
iat: (0,
|
|
1817
|
+
exp: (0, import_io_wallet_utils17.dateToSeconds)(expiresAt),
|
|
1818
|
+
iat: (0, import_io_wallet_utils17.dateToSeconds)(issuedAt),
|
|
1593
1819
|
iss: options.issuer,
|
|
1594
1820
|
key_storage: options.keyStorage,
|
|
1595
1821
|
status: options.status,
|
|
@@ -1679,8 +1905,8 @@ var WalletProvider = class {
|
|
|
1679
1905
|
* });
|
|
1680
1906
|
*/
|
|
1681
1907
|
async createItWalletAttestationJwt(options) {
|
|
1682
|
-
return (0,
|
|
1683
|
-
[
|
|
1908
|
+
return (0, import_io_wallet_utils17.dispatchByVersion)(this.specVersion, {
|
|
1909
|
+
[import_io_wallet_utils17.ItWalletSpecsVersion.V1_0]: () => {
|
|
1684
1910
|
assertV1_0Options(options);
|
|
1685
1911
|
return (0, import_io_wallet_oauth29.createWalletAttestationJwtV1_0)({
|
|
1686
1912
|
authenticatorAssuranceLevel: options.authenticatorAssuranceLevel,
|
|
@@ -1693,7 +1919,7 @@ var WalletProvider = class {
|
|
|
1693
1919
|
walletName: options.walletName
|
|
1694
1920
|
});
|
|
1695
1921
|
},
|
|
1696
|
-
[
|
|
1922
|
+
[import_io_wallet_utils17.ItWalletSpecsVersion.V1_3]: () => {
|
|
1697
1923
|
assertV1_3Options(options);
|
|
1698
1924
|
return (0, import_io_wallet_oauth29.createWalletAttestationJwtV1_3)({
|
|
1699
1925
|
callbacks: options.callbacks,
|
|
@@ -1707,7 +1933,7 @@ var WalletProvider = class {
|
|
|
1707
1933
|
walletName: options.walletName
|
|
1708
1934
|
});
|
|
1709
1935
|
},
|
|
1710
|
-
[
|
|
1936
|
+
[import_io_wallet_utils17.ItWalletSpecsVersion.V1_4]: () => {
|
|
1711
1937
|
assertV1_4Options(options);
|
|
1712
1938
|
return (0, import_io_wallet_oauth29.createWalletAttestationJwtV1_4)({
|
|
1713
1939
|
callbacks: options.callbacks,
|
|
@@ -1755,8 +1981,14 @@ var WalletProvider = class {
|
|
|
1755
1981
|
verifyAuthorizationResponseFormPostJWT,
|
|
1756
1982
|
verifyCredentialRequestJwtProof,
|
|
1757
1983
|
verifyKeyAttestationJwt,
|
|
1984
|
+
zAuthorizationCodeGrantV1_3,
|
|
1985
|
+
zAuthorizationCodeGrantV1_4,
|
|
1758
1986
|
zAuthorizationResponse,
|
|
1759
1987
|
zCredentialObject,
|
|
1988
|
+
zCredentialOfferGrantsV1_3,
|
|
1989
|
+
zCredentialOfferGrantsV1_4,
|
|
1990
|
+
zCredentialOfferV1_3,
|
|
1991
|
+
zCredentialOfferV1_4,
|
|
1760
1992
|
zCredentialRequestV1_0,
|
|
1761
1993
|
zCredentialRequestV1_3,
|
|
1762
1994
|
zCredentialResponseEncryption,
|