@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.mjs CHANGED
@@ -15,36 +15,40 @@ import {
15
15
 
16
16
  // src/errors.ts
17
17
  var Oid4vpError = class extends Error {
18
- constructor(message, statusCode) {
19
- super(message);
20
- this.statusCode = statusCode;
18
+ statusCode;
19
+ constructor(message, options) {
20
+ super(message, options);
21
21
  this.name = "Oid4vpError";
22
+ this.statusCode = options?.statusCode;
22
23
  }
23
24
  };
24
25
  var ParseAuthorizeRequestError = class extends Oid4vpError {
25
- constructor(message, statusCode) {
26
- super(message);
27
- this.statusCode = statusCode;
26
+ statusCode;
27
+ constructor(message, options) {
28
+ super(message, options);
28
29
  this.name = "ParseAuthorizeRequestError";
30
+ this.statusCode = options?.statusCode;
29
31
  }
30
32
  };
31
33
  var FetchAuthorizationResponseError = class extends Oid4vpError {
32
- constructor(message, statusCode) {
33
- super(message);
34
- this.statusCode = statusCode;
34
+ statusCode;
35
+ constructor(message, options) {
36
+ super(message, options);
35
37
  this.name = "FetchAuthorizationResponseError";
38
+ this.statusCode = options?.statusCode;
36
39
  }
37
40
  };
38
41
  var CreateAuthorizationResponseError = class extends Oid4vpError {
39
- constructor(message, statusCode) {
40
- super(message);
41
- this.statusCode = statusCode;
42
+ statusCode;
43
+ constructor(message, options) {
44
+ super(message, options);
42
45
  this.name = "CreateAuthorizationResponseError";
46
+ this.statusCode = options?.statusCode;
43
47
  }
44
48
  };
45
49
  var InvalidRequestUriMethodError = class extends Oid4vpError {
46
- constructor(message) {
47
- super(message);
50
+ constructor(message, options) {
51
+ super(message, options);
48
52
  this.name = "InvalidRequestUriMethodError";
49
53
  }
50
54
  };
@@ -348,6 +352,7 @@ async function parseAuthorizeRequest(options) {
348
352
  try {
349
353
  const headerSchema = options.config.isVersion(ItWalletSpecsVersion2.V1_0) ? zOpenid4vpAuthorizationRequestHeaderV1_0 : zOpenid4vpAuthorizationRequestHeaderV1_3;
350
354
  const decoded = decodeJwt({
355
+ errorMessagePrefix: "Error decoding authorization request JWT:",
351
356
  headerSchema,
352
357
  jwt: options.requestObjectJwt,
353
358
  payloadSchema: zOpenid4vpAuthorizationRequestPayload
@@ -401,17 +406,91 @@ function extractEncryptionJwkFromJwks(jwks, {
401
406
  return encFiltered.length > 0 ? encFiltered[0] : jwks.keys[0];
402
407
  }
403
408
 
404
- // src/jarm/parse-jarm-authorization-response.ts
409
+ // src/authorization-response/create-authorization-response.ts
410
+ async function createAuthorizationResponse(options) {
411
+ try {
412
+ const encryptionAlg = options.authorization_encrypted_response_alg ?? "ECDH-ES";
413
+ const encryptionEnc = options.authorization_encrypted_response_enc ?? "A256GCM";
414
+ const { requestObject } = options;
415
+ const clientMetadata = requestObject.client_metadata;
416
+ const clientIdPrefix = extractClientIdPrefix(requestObject.client_id);
417
+ if (clientIdPrefix === "x509_hash" /* X509_HASH */ && !clientMetadata) {
418
+ throw new CreateAuthorizationResponseError(
419
+ "clientMetadata is required when client_id uses x509_hash prefix"
420
+ );
421
+ }
422
+ const effectiveClientMetadata = clientIdPrefix === "openid_federation" /* OPENID_FEDERATION */ ? void 0 : clientMetadata;
423
+ const authorizationResponsePayload = {
424
+ state: requestObject.state,
425
+ vp_token: options.vp_token
426
+ };
427
+ const encryptionJwks = effectiveClientMetadata ? effectiveClientMetadata.jwks : options.rpJwks.jwks;
428
+ const encryptionJwk = extractEncryptionJwkFromJwks(encryptionJwks, {
429
+ supportedAlgValues: [encryptionAlg]
430
+ });
431
+ if (!encryptionJwk) {
432
+ throw new CreateAuthorizationResponseError(
433
+ "No encryption JWK found in metadata"
434
+ );
435
+ }
436
+ const encValuesSupported = effectiveClientMetadata?.encrypted_response_enc_values_supported ?? options.rpJwks.encrypted_response_enc_values_supported;
437
+ let enc;
438
+ if (encValuesSupported) {
439
+ if (options.authorization_encrypted_response_enc !== void 0) {
440
+ enc = encValuesSupported.find(
441
+ (e) => e === options.authorization_encrypted_response_enc
442
+ ) ?? encValuesSupported[0] ?? options.authorization_encrypted_response_enc;
443
+ } else {
444
+ enc = encValuesSupported[0] ?? encryptionEnc;
445
+ }
446
+ } else {
447
+ enc = encryptionEnc;
448
+ }
449
+ const alg = encryptionJwk.alg ?? encryptionAlg;
450
+ const nonceBytes = await options.callbacks.generateRandom(32);
451
+ const jweEncryptor = {
452
+ alg,
453
+ apu: encodeToBase64Url(nonceBytes),
454
+ apv: encodeToBase64Url(requestObject.nonce),
455
+ enc,
456
+ method: "jwk",
457
+ publicJwk: encryptionJwk
458
+ };
459
+ const plaintext = JSON.stringify(authorizationResponsePayload);
460
+ const { encryptionJwk: usedJwk, jwe } = await options.callbacks.encryptJwe(
461
+ jweEncryptor,
462
+ plaintext
463
+ );
464
+ return {
465
+ authorizationResponsePayload,
466
+ jarm: {
467
+ encryptionJwk: usedJwk,
468
+ responseJwe: jwe
469
+ }
470
+ };
471
+ } catch (error) {
472
+ if (error instanceof CreateAuthorizationResponseError) {
473
+ throw error;
474
+ }
475
+ throw new CreateAuthorizationResponseError(
476
+ `Unexpected error during authorization response creation: ${error instanceof Error ? error.message : String(error)}`
477
+ );
478
+ }
479
+ }
480
+
481
+ // src/authorization-response/fetch-authorization-response.ts
405
482
  import {
406
- decodeJwtHeader as decodeJwtHeader2,
407
- zCompactJwe as zCompactJwe2,
408
- zCompactJwt as zCompactJwt2
409
- } from "@pagopa/io-wallet-oauth2";
410
- import { parseWithErrorHandling as parseWithErrorHandling3 } from "@pagopa/io-wallet-utils";
411
- import z7 from "zod";
483
+ CONTENT_TYPES,
484
+ HEADERS,
485
+ UnexpectedStatusCodeError as UnexpectedStatusCodeError2,
486
+ ValidationError as ValidationError4,
487
+ createFetcher as createFetcher2,
488
+ hasStatusOrThrow as hasStatusOrThrow2,
489
+ parseWithErrorHandling as parseWithErrorHandling2
490
+ } from "@pagopa/io-wallet-utils";
412
491
 
413
- // src/vp-token/parse-vp-token.ts
414
- import { parseIfJson, parseWithErrorHandling as parseWithErrorHandling2 } from "@pagopa/io-wallet-utils";
492
+ // src/authorization-response/z-authorization-response.ts
493
+ import z4 from "zod";
415
494
 
416
495
  // src/vp-token/z-vp-token.ts
417
496
  import { z as z3 } from "zod";
@@ -423,9 +502,66 @@ var zVpToken = z3.record(
423
502
  }
424
503
  );
425
504
 
505
+ // src/authorization-response/z-authorization-response.ts
506
+ var zOpenid4vpAuthorizationResponse = z4.object({
507
+ state: z4.string(),
508
+ vp_token: zVpToken
509
+ });
510
+ var zOpenid4vpAuthorizationResponseResult = z4.object({
511
+ redirect_uri: z4.url().optional()
512
+ });
513
+
514
+ // src/authorization-response/fetch-authorization-response.ts
515
+ async function fetchAuthorizationResponse(options) {
516
+ try {
517
+ const fetch = createFetcher2(options.callbacks.fetch);
518
+ const authorizationResponseResult = await fetch(
519
+ options.presentationResponseUri,
520
+ {
521
+ body: new URLSearchParams({
522
+ response: options.authorizationResponseJarm
523
+ }),
524
+ headers: {
525
+ [HEADERS.CONTENT_TYPE]: CONTENT_TYPES.FORM_URLENCODED
526
+ },
527
+ method: "POST"
528
+ }
529
+ );
530
+ await hasStatusOrThrow2(
531
+ 200,
532
+ UnexpectedStatusCodeError2
533
+ )(authorizationResponseResult);
534
+ const authorizationResponseResultJson = await authorizationResponseResult.json();
535
+ return parseWithErrorHandling2(
536
+ zOpenid4vpAuthorizationResponseResult,
537
+ authorizationResponseResultJson
538
+ );
539
+ } catch (error) {
540
+ if (error instanceof UnexpectedStatusCodeError2 || error instanceof ValidationError4) {
541
+ throw error;
542
+ }
543
+ throw new FetchAuthorizationResponseError(
544
+ `Unexpected error sending authorization response: ${error instanceof Error ? error.message : String(error)}`
545
+ );
546
+ }
547
+ }
548
+
549
+ // src/authorization-response/parse-authorization-response.ts
550
+ import { parseWithErrorHandling as parseWithErrorHandling5 } from "@pagopa/io-wallet-utils";
551
+
552
+ // src/jarm/parse-jarm-authorization-response.ts
553
+ import {
554
+ decodeJwtHeader as decodeJwtHeader2,
555
+ zCompactJwe as zCompactJwe2,
556
+ zCompactJwt as zCompactJwt2
557
+ } from "@pagopa/io-wallet-oauth2";
558
+ import { parseWithErrorHandling as parseWithErrorHandling4 } from "@pagopa/io-wallet-utils";
559
+ import z7 from "zod";
560
+
426
561
  // src/vp-token/parse-vp-token.ts
562
+ import { parseIfJson, parseWithErrorHandling as parseWithErrorHandling3 } from "@pagopa/io-wallet-utils";
427
563
  function parseVpToken(vpToken) {
428
- return parseWithErrorHandling2(
564
+ return parseWithErrorHandling3(
429
565
  zVpToken,
430
566
  parseIfJson(vpToken),
431
567
  "Could not parse dcql vp_token. Expected an object where the values are encoded presentations"
@@ -445,16 +581,6 @@ function validateOpenid4vpAuthorizationResponsePayload(options) {
445
581
  };
446
582
  }
447
583
 
448
- // src/authorization-response/z-authorization-response.ts
449
- import z4 from "zod";
450
- var zOpenid4vpAuthorizationResponse = z4.object({
451
- state: z4.string(),
452
- vp_token: zVpToken
453
- });
454
- var zOpenid4vpAuthorizationResponseResult = z4.object({
455
- redirect_uri: z4.url().optional()
456
- });
457
-
458
584
  // src/jarm/verify-jarm-authorization-response.ts
459
585
  import { jwtSignerFromJwt } from "@openid4vc/oauth2";
460
586
  import {
@@ -557,6 +683,7 @@ async function verifyJarmAuthorizationResponse(options) {
557
683
  let jarmAuthorizationResponse;
558
684
  if (responseIsSigned) {
559
685
  const { header: jwsProtectedHeader, payload: jwsPayload } = decodeJwt2({
686
+ errorMessagePrefix: "Error decoding JARM authorization response JWT:",
560
687
  headerSchema: z6.object({ ...zJwtHeader2.shape, kid: z6.string() }),
561
688
  jwt: decryptedRequestData.payload
562
689
  });
@@ -614,7 +741,7 @@ async function verifyJarmAuthorizationResponse(options) {
614
741
  // src/jarm/parse-jarm-authorization-response.ts
615
742
  async function parseJarmAuthorizationResponse(options) {
616
743
  const { authorizationRequestPayload, callbacks, jarmResponseJwt, now } = options;
617
- const jarmAuthorizationResponseJwt = parseWithErrorHandling3(
744
+ const jarmAuthorizationResponseJwt = parseWithErrorHandling4(
618
745
  z7.union([zCompactJwt2, zCompactJwe2]),
619
746
  jarmResponseJwt,
620
747
  "Invalid jarm authorization response jwt."
@@ -629,7 +756,7 @@ async function parseJarmAuthorizationResponse(options) {
629
756
  headerSchema: zJarmHeader,
630
757
  jwt: jarmAuthorizationResponseJwt
631
758
  });
632
- const authorizationResponsePayload = parseWithErrorHandling3(
759
+ const authorizationResponsePayload = parseWithErrorHandling4(
633
760
  zOpenid4vpAuthorizationResponse,
634
761
  verifiedJarmResponse.jarmAuthorizationResponse,
635
762
  "Failed to parse openid4vp authorization response."
@@ -646,124 +773,7 @@ async function parseJarmAuthorizationResponse(options) {
646
773
  };
647
774
  }
648
775
 
649
- // src/authorization-response/create-authorization-response.ts
650
- async function createAuthorizationResponse(options) {
651
- try {
652
- const encryptionAlg = options.authorization_encrypted_response_alg ?? "ECDH-ES";
653
- const encryptionEnc = options.authorization_encrypted_response_enc ?? "A256GCM";
654
- const { requestObject } = options;
655
- const clientMetadata = requestObject.client_metadata;
656
- const clientIdPrefix = extractClientIdPrefix(requestObject.client_id);
657
- if (clientIdPrefix === "x509_hash" /* X509_HASH */ && !clientMetadata) {
658
- throw new CreateAuthorizationResponseError(
659
- "clientMetadata is required when client_id uses x509_hash prefix"
660
- );
661
- }
662
- const effectiveClientMetadata = clientIdPrefix === "openid_federation" /* OPENID_FEDERATION */ ? void 0 : clientMetadata;
663
- const authorizationResponsePayload = {
664
- state: requestObject.state,
665
- vp_token: options.vp_token
666
- };
667
- const encryptionJwks = effectiveClientMetadata ? effectiveClientMetadata.jwks : options.rpJwks.jwks;
668
- const encryptionJwk = extractEncryptionJwkFromJwks(encryptionJwks, {
669
- supportedAlgValues: [encryptionAlg]
670
- });
671
- if (!encryptionJwk) {
672
- throw new CreateAuthorizationResponseError(
673
- "No encryption JWK found in metadata"
674
- );
675
- }
676
- const encValuesSupported = effectiveClientMetadata?.encrypted_response_enc_values_supported ?? options.rpJwks.encrypted_response_enc_values_supported;
677
- let enc;
678
- if (encValuesSupported) {
679
- if (options.authorization_encrypted_response_enc !== void 0) {
680
- enc = encValuesSupported.find(
681
- (e) => e === options.authorization_encrypted_response_enc
682
- ) ?? encValuesSupported[0] ?? options.authorization_encrypted_response_enc;
683
- } else {
684
- enc = encValuesSupported[0] ?? encryptionEnc;
685
- }
686
- } else {
687
- enc = encryptionEnc;
688
- }
689
- const alg = encryptionJwk.alg ?? encryptionAlg;
690
- const nonceBytes = await options.callbacks.generateRandom(32);
691
- const jweEncryptor = {
692
- alg,
693
- apu: encodeToBase64Url(nonceBytes),
694
- apv: encodeToBase64Url(requestObject.nonce),
695
- enc,
696
- method: "jwk",
697
- publicJwk: encryptionJwk
698
- };
699
- const plaintext = JSON.stringify(authorizationResponsePayload);
700
- const { encryptionJwk: usedJwk, jwe } = await options.callbacks.encryptJwe(
701
- jweEncryptor,
702
- plaintext
703
- );
704
- return {
705
- authorizationResponsePayload,
706
- jarm: {
707
- encryptionJwk: usedJwk,
708
- responseJwe: jwe
709
- }
710
- };
711
- } catch (error) {
712
- if (error instanceof CreateAuthorizationResponseError) {
713
- throw error;
714
- }
715
- throw new CreateAuthorizationResponseError(
716
- `Unexpected error during authorization response creation: ${error instanceof Error ? error.message : String(error)}`
717
- );
718
- }
719
- }
720
-
721
- // src/authorization-response/fetch-authorization-response.ts
722
- import {
723
- CONTENT_TYPES,
724
- HEADERS,
725
- UnexpectedStatusCodeError as UnexpectedStatusCodeError2,
726
- ValidationError as ValidationError4,
727
- createFetcher as createFetcher2,
728
- hasStatusOrThrow as hasStatusOrThrow2,
729
- parseWithErrorHandling as parseWithErrorHandling4
730
- } from "@pagopa/io-wallet-utils";
731
- async function fetchAuthorizationResponse(options) {
732
- try {
733
- const fetch = createFetcher2(options.callbacks.fetch);
734
- const authorizationResponseResult = await fetch(
735
- options.presentationResponseUri,
736
- {
737
- body: new URLSearchParams({
738
- response: options.authorizationResponseJarm
739
- }),
740
- headers: {
741
- [HEADERS.CONTENT_TYPE]: CONTENT_TYPES.FORM_URLENCODED
742
- },
743
- method: "POST"
744
- }
745
- );
746
- await hasStatusOrThrow2(
747
- 200,
748
- UnexpectedStatusCodeError2
749
- )(authorizationResponseResult);
750
- const authorizationResponseResultJson = await authorizationResponseResult.json();
751
- return parseWithErrorHandling4(
752
- zOpenid4vpAuthorizationResponseResult,
753
- authorizationResponseResultJson
754
- );
755
- } catch (error) {
756
- if (error instanceof UnexpectedStatusCodeError2 || error instanceof ValidationError4) {
757
- throw error;
758
- }
759
- throw new FetchAuthorizationResponseError(
760
- `Unexpected error sending authorization response: ${error instanceof Error ? error.message : String(error)}`
761
- );
762
- }
763
- }
764
-
765
776
  // src/authorization-response/parse-authorization-response.ts
766
- import { parseWithErrorHandling as parseWithErrorHandling5 } from "@pagopa/io-wallet-utils";
767
777
  async function parseAuthorizationResponse(options) {
768
778
  const { authorizationRequestPayload, authorizationResponse, callbacks } = options;
769
779
  if (authorizationResponse.response) {