@pagopa/io-wallet-oid4vp 1.2.0 → 1.3.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.js CHANGED
@@ -72,36 +72,40 @@ var import_io_wallet_utils = require("@pagopa/io-wallet-utils");
72
72
 
73
73
  // src/errors.ts
74
74
  var Oid4vpError = class extends Error {
75
- constructor(message, statusCode) {
76
- super(message);
77
- this.statusCode = statusCode;
75
+ statusCode;
76
+ constructor(message, options) {
77
+ super(message, options);
78
78
  this.name = "Oid4vpError";
79
+ this.statusCode = options?.statusCode;
79
80
  }
80
81
  };
81
82
  var ParseAuthorizeRequestError = class extends Oid4vpError {
82
- constructor(message, statusCode) {
83
- super(message);
84
- this.statusCode = statusCode;
83
+ statusCode;
84
+ constructor(message, options) {
85
+ super(message, options);
85
86
  this.name = "ParseAuthorizeRequestError";
87
+ this.statusCode = options?.statusCode;
86
88
  }
87
89
  };
88
90
  var FetchAuthorizationResponseError = class extends Oid4vpError {
89
- constructor(message, statusCode) {
90
- super(message);
91
- this.statusCode = statusCode;
91
+ statusCode;
92
+ constructor(message, options) {
93
+ super(message, options);
92
94
  this.name = "FetchAuthorizationResponseError";
95
+ this.statusCode = options?.statusCode;
93
96
  }
94
97
  };
95
98
  var CreateAuthorizationResponseError = class extends Oid4vpError {
96
- constructor(message, statusCode) {
97
- super(message);
98
- this.statusCode = statusCode;
99
+ statusCode;
100
+ constructor(message, options) {
101
+ super(message, options);
99
102
  this.name = "CreateAuthorizationResponseError";
103
+ this.statusCode = options?.statusCode;
100
104
  }
101
105
  };
102
106
  var InvalidRequestUriMethodError = class extends Oid4vpError {
103
- constructor(message) {
104
- super(message);
107
+ constructor(message, options) {
108
+ super(message, options);
105
109
  this.name = "InvalidRequestUriMethodError";
106
110
  }
107
111
  };
@@ -388,6 +392,7 @@ async function parseAuthorizeRequest(options) {
388
392
  try {
389
393
  const headerSchema = options.config.isVersion(import_io_wallet_utils3.ItWalletSpecsVersion.V1_0) ? zOpenid4vpAuthorizationRequestHeaderV1_0 : zOpenid4vpAuthorizationRequestHeaderV1_3;
390
394
  const decoded = (0, import_io_wallet_oauth23.decodeJwt)({
395
+ errorMessagePrefix: "Error decoding authorization request JWT:",
391
396
  headerSchema,
392
397
  jwt: options.requestObjectJwt,
393
398
  payloadSchema: zOpenid4vpAuthorizationRequestPayload
@@ -420,7 +425,7 @@ async function parseAuthorizeRequest(options) {
420
425
  }
421
426
 
422
427
  // src/authorization-response/create-authorization-response.ts
423
- var import_io_wallet_utils7 = require("@pagopa/io-wallet-utils");
428
+ var import_io_wallet_utils4 = require("@pagopa/io-wallet-utils");
424
429
 
425
430
  // src/jarm/jarm-extract-jwks.ts
426
431
  function extractEncryptionJwkFromJwks(jwks, {
@@ -441,13 +446,83 @@ function extractEncryptionJwkFromJwks(jwks, {
441
446
  return encFiltered.length > 0 ? encFiltered[0] : jwks.keys[0];
442
447
  }
443
448
 
444
- // src/jarm/parse-jarm-authorization-response.ts
445
- var import_io_wallet_oauth26 = require("@pagopa/io-wallet-oauth2");
446
- var import_io_wallet_utils6 = require("@pagopa/io-wallet-utils");
447
- var import_zod7 = __toESM(require("zod"));
449
+ // src/authorization-response/create-authorization-response.ts
450
+ async function createAuthorizationResponse(options) {
451
+ try {
452
+ const encryptionAlg = options.authorization_encrypted_response_alg ?? "ECDH-ES";
453
+ const encryptionEnc = options.authorization_encrypted_response_enc ?? "A256GCM";
454
+ const { requestObject } = options;
455
+ const clientMetadata = requestObject.client_metadata;
456
+ const clientIdPrefix = extractClientIdPrefix(requestObject.client_id);
457
+ if (clientIdPrefix === "x509_hash" /* X509_HASH */ && !clientMetadata) {
458
+ throw new CreateAuthorizationResponseError(
459
+ "clientMetadata is required when client_id uses x509_hash prefix"
460
+ );
461
+ }
462
+ const effectiveClientMetadata = clientIdPrefix === "openid_federation" /* OPENID_FEDERATION */ ? void 0 : clientMetadata;
463
+ const authorizationResponsePayload = {
464
+ state: requestObject.state,
465
+ vp_token: options.vp_token
466
+ };
467
+ const encryptionJwks = effectiveClientMetadata ? effectiveClientMetadata.jwks : options.rpJwks.jwks;
468
+ const encryptionJwk = extractEncryptionJwkFromJwks(encryptionJwks, {
469
+ supportedAlgValues: [encryptionAlg]
470
+ });
471
+ if (!encryptionJwk) {
472
+ throw new CreateAuthorizationResponseError(
473
+ "No encryption JWK found in metadata"
474
+ );
475
+ }
476
+ const encValuesSupported = effectiveClientMetadata?.encrypted_response_enc_values_supported ?? options.rpJwks.encrypted_response_enc_values_supported;
477
+ let enc;
478
+ if (encValuesSupported) {
479
+ if (options.authorization_encrypted_response_enc !== void 0) {
480
+ enc = encValuesSupported.find(
481
+ (e) => e === options.authorization_encrypted_response_enc
482
+ ) ?? encValuesSupported[0] ?? options.authorization_encrypted_response_enc;
483
+ } else {
484
+ enc = encValuesSupported[0] ?? encryptionEnc;
485
+ }
486
+ } else {
487
+ enc = encryptionEnc;
488
+ }
489
+ const alg = encryptionJwk.alg ?? encryptionAlg;
490
+ const nonceBytes = await options.callbacks.generateRandom(32);
491
+ const jweEncryptor = {
492
+ alg,
493
+ apu: (0, import_io_wallet_utils4.encodeToBase64Url)(nonceBytes),
494
+ apv: (0, import_io_wallet_utils4.encodeToBase64Url)(requestObject.nonce),
495
+ enc,
496
+ method: "jwk",
497
+ publicJwk: encryptionJwk
498
+ };
499
+ const plaintext = JSON.stringify(authorizationResponsePayload);
500
+ const { encryptionJwk: usedJwk, jwe } = await options.callbacks.encryptJwe(
501
+ jweEncryptor,
502
+ plaintext
503
+ );
504
+ return {
505
+ authorizationResponsePayload,
506
+ jarm: {
507
+ encryptionJwk: usedJwk,
508
+ responseJwe: jwe
509
+ }
510
+ };
511
+ } catch (error) {
512
+ if (error instanceof CreateAuthorizationResponseError) {
513
+ throw error;
514
+ }
515
+ throw new CreateAuthorizationResponseError(
516
+ `Unexpected error during authorization response creation: ${error instanceof Error ? error.message : String(error)}`
517
+ );
518
+ }
519
+ }
448
520
 
449
- // src/vp-token/parse-vp-token.ts
450
- var import_io_wallet_utils4 = require("@pagopa/io-wallet-utils");
521
+ // src/authorization-response/fetch-authorization-response.ts
522
+ var import_io_wallet_utils5 = require("@pagopa/io-wallet-utils");
523
+
524
+ // src/authorization-response/z-authorization-response.ts
525
+ var import_zod4 = __toESM(require("zod"));
451
526
 
452
527
  // src/vp-token/z-vp-token.ts
453
528
  var import_zod3 = require("zod");
@@ -459,11 +534,64 @@ var zVpToken = import_zod3.z.record(
459
534
  }
460
535
  );
461
536
 
537
+ // src/authorization-response/z-authorization-response.ts
538
+ var zOpenid4vpAuthorizationResponse = import_zod4.default.object({
539
+ state: import_zod4.default.string(),
540
+ vp_token: zVpToken
541
+ });
542
+ var zOpenid4vpAuthorizationResponseResult = import_zod4.default.object({
543
+ redirect_uri: import_zod4.default.url().optional()
544
+ });
545
+
546
+ // src/authorization-response/fetch-authorization-response.ts
547
+ async function fetchAuthorizationResponse(options) {
548
+ try {
549
+ const fetch = (0, import_io_wallet_utils5.createFetcher)(options.callbacks.fetch);
550
+ const authorizationResponseResult = await fetch(
551
+ options.presentationResponseUri,
552
+ {
553
+ body: new URLSearchParams({
554
+ response: options.authorizationResponseJarm
555
+ }),
556
+ headers: {
557
+ [import_io_wallet_utils5.HEADERS.CONTENT_TYPE]: import_io_wallet_utils5.CONTENT_TYPES.FORM_URLENCODED
558
+ },
559
+ method: "POST"
560
+ }
561
+ );
562
+ await (0, import_io_wallet_utils5.hasStatusOrThrow)(
563
+ 200,
564
+ import_io_wallet_utils5.UnexpectedStatusCodeError
565
+ )(authorizationResponseResult);
566
+ const authorizationResponseResultJson = await authorizationResponseResult.json();
567
+ return (0, import_io_wallet_utils5.parseWithErrorHandling)(
568
+ zOpenid4vpAuthorizationResponseResult,
569
+ authorizationResponseResultJson
570
+ );
571
+ } catch (error) {
572
+ if (error instanceof import_io_wallet_utils5.UnexpectedStatusCodeError || error instanceof import_io_wallet_utils5.ValidationError) {
573
+ throw error;
574
+ }
575
+ throw new FetchAuthorizationResponseError(
576
+ `Unexpected error sending authorization response: ${error instanceof Error ? error.message : String(error)}`
577
+ );
578
+ }
579
+ }
580
+
581
+ // src/authorization-response/parse-authorization-response.ts
582
+ var import_io_wallet_utils9 = require("@pagopa/io-wallet-utils");
583
+
584
+ // src/jarm/parse-jarm-authorization-response.ts
585
+ var import_io_wallet_oauth26 = require("@pagopa/io-wallet-oauth2");
586
+ var import_io_wallet_utils8 = require("@pagopa/io-wallet-utils");
587
+ var import_zod7 = __toESM(require("zod"));
588
+
462
589
  // src/vp-token/parse-vp-token.ts
590
+ var import_io_wallet_utils6 = require("@pagopa/io-wallet-utils");
463
591
  function parseVpToken(vpToken) {
464
- return (0, import_io_wallet_utils4.parseWithErrorHandling)(
592
+ return (0, import_io_wallet_utils6.parseWithErrorHandling)(
465
593
  zVpToken,
466
- (0, import_io_wallet_utils4.parseIfJson)(vpToken),
594
+ (0, import_io_wallet_utils6.parseIfJson)(vpToken),
467
595
  "Could not parse dcql vp_token. Expected an object where the values are encoded presentations"
468
596
  );
469
597
  }
@@ -481,20 +609,10 @@ function validateOpenid4vpAuthorizationResponsePayload(options) {
481
609
  };
482
610
  }
483
611
 
484
- // src/authorization-response/z-authorization-response.ts
485
- var import_zod4 = __toESM(require("zod"));
486
- var zOpenid4vpAuthorizationResponse = import_zod4.default.object({
487
- state: import_zod4.default.string(),
488
- vp_token: zVpToken
489
- });
490
- var zOpenid4vpAuthorizationResponseResult = import_zod4.default.object({
491
- redirect_uri: import_zod4.default.url().optional()
492
- });
493
-
494
612
  // src/jarm/verify-jarm-authorization-response.ts
495
613
  var import_oauth23 = require("@openid4vc/oauth2");
496
614
  var import_io_wallet_oauth25 = require("@pagopa/io-wallet-oauth2");
497
- var import_io_wallet_utils5 = require("@pagopa/io-wallet-utils");
615
+ var import_io_wallet_utils7 = require("@pagopa/io-wallet-utils");
498
616
  var import_zod6 = __toESM(require("zod"));
499
617
 
500
618
  // src/jarm/z-jarm.ts
@@ -586,6 +704,7 @@ async function verifyJarmAuthorizationResponse(options) {
586
704
  let jarmAuthorizationResponse;
587
705
  if (responseIsSigned) {
588
706
  const { header: jwsProtectedHeader, payload: jwsPayload } = (0, import_io_wallet_oauth25.decodeJwt)({
707
+ errorMessagePrefix: "Error decoding JARM authorization response JWT:",
589
708
  headerSchema: import_zod6.default.object({ ...import_io_wallet_oauth25.zJwtHeader.shape, kid: import_zod6.default.string() }),
590
709
  jwt: decryptedRequestData.payload
591
710
  });
@@ -624,7 +743,7 @@ async function verifyJarmAuthorizationResponse(options) {
624
743
  }
625
744
  jarmAuthorizationResponse = response;
626
745
  } else {
627
- const jsonRequestData = (0, import_io_wallet_utils5.stringToJsonWithErrorHandling)(
746
+ const jsonRequestData = (0, import_io_wallet_utils7.stringToJsonWithErrorHandling)(
628
747
  decryptedRequestData.payload,
629
748
  "Unable to parse decrypted JARM JWE body to JSON"
630
749
  );
@@ -643,7 +762,7 @@ async function verifyJarmAuthorizationResponse(options) {
643
762
  // src/jarm/parse-jarm-authorization-response.ts
644
763
  async function parseJarmAuthorizationResponse(options) {
645
764
  const { authorizationRequestPayload, callbacks, jarmResponseJwt, now } = options;
646
- const jarmAuthorizationResponseJwt = (0, import_io_wallet_utils6.parseWithErrorHandling)(
765
+ const jarmAuthorizationResponseJwt = (0, import_io_wallet_utils8.parseWithErrorHandling)(
647
766
  import_zod7.default.union([import_io_wallet_oauth26.zCompactJwt, import_io_wallet_oauth26.zCompactJwe]),
648
767
  jarmResponseJwt,
649
768
  "Invalid jarm authorization response jwt."
@@ -658,7 +777,7 @@ async function parseJarmAuthorizationResponse(options) {
658
777
  headerSchema: zJarmHeader,
659
778
  jwt: jarmAuthorizationResponseJwt
660
779
  });
661
- const authorizationResponsePayload = (0, import_io_wallet_utils6.parseWithErrorHandling)(
780
+ const authorizationResponsePayload = (0, import_io_wallet_utils8.parseWithErrorHandling)(
662
781
  zOpenid4vpAuthorizationResponse,
663
782
  verifiedJarmResponse.jarmAuthorizationResponse,
664
783
  "Failed to parse openid4vp authorization response."
@@ -675,116 +794,7 @@ async function parseJarmAuthorizationResponse(options) {
675
794
  };
676
795
  }
677
796
 
678
- // src/authorization-response/create-authorization-response.ts
679
- async function createAuthorizationResponse(options) {
680
- try {
681
- const encryptionAlg = options.authorization_encrypted_response_alg ?? "ECDH-ES";
682
- const encryptionEnc = options.authorization_encrypted_response_enc ?? "A256GCM";
683
- const { requestObject } = options;
684
- const clientMetadata = requestObject.client_metadata;
685
- const clientIdPrefix = extractClientIdPrefix(requestObject.client_id);
686
- if (clientIdPrefix === "x509_hash" /* X509_HASH */ && !clientMetadata) {
687
- throw new CreateAuthorizationResponseError(
688
- "clientMetadata is required when client_id uses x509_hash prefix"
689
- );
690
- }
691
- const effectiveClientMetadata = clientIdPrefix === "openid_federation" /* OPENID_FEDERATION */ ? void 0 : clientMetadata;
692
- const authorizationResponsePayload = {
693
- state: requestObject.state,
694
- vp_token: options.vp_token
695
- };
696
- const encryptionJwks = effectiveClientMetadata ? effectiveClientMetadata.jwks : options.rpJwks.jwks;
697
- const encryptionJwk = extractEncryptionJwkFromJwks(encryptionJwks, {
698
- supportedAlgValues: [encryptionAlg]
699
- });
700
- if (!encryptionJwk) {
701
- throw new CreateAuthorizationResponseError(
702
- "No encryption JWK found in metadata"
703
- );
704
- }
705
- const encValuesSupported = effectiveClientMetadata?.encrypted_response_enc_values_supported ?? options.rpJwks.encrypted_response_enc_values_supported;
706
- let enc;
707
- if (encValuesSupported) {
708
- if (options.authorization_encrypted_response_enc !== void 0) {
709
- enc = encValuesSupported.find(
710
- (e) => e === options.authorization_encrypted_response_enc
711
- ) ?? encValuesSupported[0] ?? options.authorization_encrypted_response_enc;
712
- } else {
713
- enc = encValuesSupported[0] ?? encryptionEnc;
714
- }
715
- } else {
716
- enc = encryptionEnc;
717
- }
718
- const alg = encryptionJwk.alg ?? encryptionAlg;
719
- const nonceBytes = await options.callbacks.generateRandom(32);
720
- const jweEncryptor = {
721
- alg,
722
- apu: (0, import_io_wallet_utils7.encodeToBase64Url)(nonceBytes),
723
- apv: (0, import_io_wallet_utils7.encodeToBase64Url)(requestObject.nonce),
724
- enc,
725
- method: "jwk",
726
- publicJwk: encryptionJwk
727
- };
728
- const plaintext = JSON.stringify(authorizationResponsePayload);
729
- const { encryptionJwk: usedJwk, jwe } = await options.callbacks.encryptJwe(
730
- jweEncryptor,
731
- plaintext
732
- );
733
- return {
734
- authorizationResponsePayload,
735
- jarm: {
736
- encryptionJwk: usedJwk,
737
- responseJwe: jwe
738
- }
739
- };
740
- } catch (error) {
741
- if (error instanceof CreateAuthorizationResponseError) {
742
- throw error;
743
- }
744
- throw new CreateAuthorizationResponseError(
745
- `Unexpected error during authorization response creation: ${error instanceof Error ? error.message : String(error)}`
746
- );
747
- }
748
- }
749
-
750
- // src/authorization-response/fetch-authorization-response.ts
751
- var import_io_wallet_utils8 = require("@pagopa/io-wallet-utils");
752
- async function fetchAuthorizationResponse(options) {
753
- try {
754
- const fetch = (0, import_io_wallet_utils8.createFetcher)(options.callbacks.fetch);
755
- const authorizationResponseResult = await fetch(
756
- options.presentationResponseUri,
757
- {
758
- body: new URLSearchParams({
759
- response: options.authorizationResponseJarm
760
- }),
761
- headers: {
762
- [import_io_wallet_utils8.HEADERS.CONTENT_TYPE]: import_io_wallet_utils8.CONTENT_TYPES.FORM_URLENCODED
763
- },
764
- method: "POST"
765
- }
766
- );
767
- await (0, import_io_wallet_utils8.hasStatusOrThrow)(
768
- 200,
769
- import_io_wallet_utils8.UnexpectedStatusCodeError
770
- )(authorizationResponseResult);
771
- const authorizationResponseResultJson = await authorizationResponseResult.json();
772
- return (0, import_io_wallet_utils8.parseWithErrorHandling)(
773
- zOpenid4vpAuthorizationResponseResult,
774
- authorizationResponseResultJson
775
- );
776
- } catch (error) {
777
- if (error instanceof import_io_wallet_utils8.UnexpectedStatusCodeError || error instanceof import_io_wallet_utils8.ValidationError) {
778
- throw error;
779
- }
780
- throw new FetchAuthorizationResponseError(
781
- `Unexpected error sending authorization response: ${error instanceof Error ? error.message : String(error)}`
782
- );
783
- }
784
- }
785
-
786
797
  // src/authorization-response/parse-authorization-response.ts
787
- var import_io_wallet_utils9 = require("@pagopa/io-wallet-utils");
788
798
  async function parseAuthorizationResponse(options) {
789
799
  const { authorizationRequestPayload, authorizationResponse, callbacks } = options;
790
800
  if (authorizationResponse.response) {