@openid4vc/oauth2 0.3.0-alpha-20250324183425 → 0.3.0-alpha-20250328112257

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
@@ -31,7 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  HashAlgorithm: () => HashAlgorithm,
34
- InvalidFetchResponseError: () => import_utils43.InvalidFetchResponseError,
34
+ InvalidFetchResponseError: () => import_utils46.InvalidFetchResponseError,
35
35
  Oauth2AuthorizationServer: () => Oauth2AuthorizationServer,
36
36
  Oauth2Client: () => Oauth2Client,
37
37
  Oauth2ClientAuthorizationChallengeError: () => Oauth2ClientAuthorizationChallengeError,
@@ -45,26 +45,30 @@ __export(src_exports, {
45
45
  Oauth2ServerErrorResponseError: () => Oauth2ServerErrorResponseError,
46
46
  PkceCodeChallengeMethod: () => PkceCodeChallengeMethod,
47
47
  SupportedAuthenticationScheme: () => SupportedAuthenticationScheme,
48
+ SupportedClientAuthenticationMethod: () => SupportedClientAuthenticationMethod,
48
49
  authorizationCodeGrantIdentifier: () => authorizationCodeGrantIdentifier,
49
50
  calculateJwkThumbprint: () => calculateJwkThumbprint,
51
+ clientAuthenticationAnonymous: () => clientAuthenticationAnonymous,
52
+ clientAuthenticationClientAttestationJwt: () => clientAuthenticationClientAttestationJwt,
50
53
  clientAuthenticationClientSecretBasic: () => clientAuthenticationClientSecretBasic,
51
54
  clientAuthenticationClientSecretPost: () => clientAuthenticationClientSecretPost,
52
55
  clientAuthenticationDynamic: () => clientAuthenticationDynamic,
53
56
  clientAuthenticationNone: () => clientAuthenticationNone,
57
+ createClientAttestationJwt: () => createClientAttestationJwt,
54
58
  decodeJwt: () => decodeJwt,
55
59
  decodeJwtHeader: () => decodeJwtHeader,
56
60
  fetchAuthorizationServerMetadata: () => fetchAuthorizationServerMetadata,
57
61
  fetchJwks: () => fetchJwks,
58
62
  fetchWellKnownMetadata: () => fetchWellKnownMetadata,
59
63
  getAuthorizationServerMetadataFromList: () => getAuthorizationServerMetadataFromList,
60
- getGlobalConfig: () => import_utils42.getGlobalConfig,
64
+ getGlobalConfig: () => import_utils45.getGlobalConfig,
61
65
  isJwkInSet: () => isJwkInSet,
62
66
  jwtHeaderFromJwtSigner: () => jwtHeaderFromJwtSigner,
63
67
  jwtSignerFromJwt: () => jwtSignerFromJwt,
64
68
  preAuthorizedCodeGrantIdentifier: () => preAuthorizedCodeGrantIdentifier,
65
69
  refreshTokenGrantIdentifier: () => refreshTokenGrantIdentifier,
66
70
  resourceRequest: () => resourceRequest,
67
- setGlobalConfig: () => import_utils42.setGlobalConfig,
71
+ setGlobalConfig: () => import_utils45.setGlobalConfig,
68
72
  verifyJwt: () => verifyJwt,
69
73
  verifyResourceRequest: () => verifyResourceRequest,
70
74
  zAlgValueNotNone: () => zAlgValueNotNone,
@@ -81,7 +85,7 @@ __export(src_exports, {
81
85
  zRefreshTokenGrantIdentifier: () => zRefreshTokenGrantIdentifier
82
86
  });
83
87
  module.exports = __toCommonJS(src_exports);
84
- var import_utils42 = require("@openid4vc/utils");
88
+ var import_utils45 = require("@openid4vc/utils");
85
89
 
86
90
  // src/common/z-oauth2-error.ts
87
91
  var import_zod = __toESM(require("zod"));
@@ -501,8 +505,305 @@ var zCompactJwe = import_zod6.z.string().regex(/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*\
501
505
  message: "Not a valid compact jwe"
502
506
  });
503
507
 
508
+ // src/client-attestation/clent-attestation.ts
509
+ var import_utils8 = require("@openid4vc/utils");
510
+
511
+ // src/common/jwt/verify-jwt.ts
512
+ var import_utils5 = require("@openid4vc/utils");
513
+
514
+ // src/error/Oauth2JwtVerificationError.ts
515
+ var Oauth2JwtVerificationError = class extends Oauth2Error {
516
+ constructor(message, options) {
517
+ const errorMessage = message ?? "Error verifiying jwt.";
518
+ super(errorMessage, options);
519
+ }
520
+ };
521
+
522
+ // src/common/jwt/verify-jwt.ts
523
+ async function verifyJwt(options) {
524
+ const errorMessage = options.errorMessage ?? "Error during verification of jwt.";
525
+ let signerJwk;
526
+ try {
527
+ const result = await options.verifyJwtCallback(options.signer, {
528
+ header: options.header,
529
+ payload: options.payload,
530
+ compact: options.compact
531
+ });
532
+ if (!result.verified) throw new Oauth2JwtVerificationError(errorMessage);
533
+ signerJwk = result.signerJwk;
534
+ } catch (error) {
535
+ if (error instanceof Oauth2JwtVerificationError) throw error;
536
+ throw new Oauth2JwtVerificationError(errorMessage, { cause: error });
537
+ }
538
+ const nowInSeconds = (0, import_utils5.dateToSeconds)(options.now ?? /* @__PURE__ */ new Date());
539
+ const skewInSeconds = options.allowedSkewInSeconds ?? 0;
540
+ const timeBasedValidation = options.skipTimeBasedValidation !== void 0 ? !options.skipTimeBasedValidation : true;
541
+ if (timeBasedValidation && options.payload.nbf && nowInSeconds < options.payload.nbf - skewInSeconds) {
542
+ throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'nbf' is in the future`);
543
+ }
544
+ if (timeBasedValidation && options.payload.exp && nowInSeconds > options.payload.exp + skewInSeconds) {
545
+ throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'exp' is in the past`);
546
+ }
547
+ if (options.expectedAudience && options.expectedAudience !== options.payload.aud) {
548
+ throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'aud' does not match expected value.`);
549
+ }
550
+ if (options.expectedIssuer && options.expectedIssuer !== options.payload.iss) {
551
+ throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'iss' does not match expected value.`);
552
+ }
553
+ if (options.expectedNonce && options.expectedNonce !== options.payload.nonce) {
554
+ throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'nonce' does not match expected value.`);
555
+ }
556
+ if (options.expectedSubject && options.expectedSubject !== options.payload.sub) {
557
+ throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'sub' does not match expected value.`);
558
+ }
559
+ if (options.requiredClaims) {
560
+ for (const claim of options.requiredClaims) {
561
+ if (!options.payload[claim]) {
562
+ throw new Oauth2JwtVerificationError(`${errorMessage} jwt '${claim}' is missing.`);
563
+ }
564
+ }
565
+ }
566
+ return {
567
+ signer: {
568
+ ...options.signer,
569
+ publicJwk: signerJwk
570
+ }
571
+ };
572
+ }
573
+
574
+ // src/error/Oauth2ServerErrorResponseError.ts
575
+ var Oauth2ServerErrorResponseError = class extends Oauth2Error {
576
+ constructor(errorResponse, options) {
577
+ super(
578
+ `${options?.internalMessage ?? errorResponse.error_description}
579
+ ${JSON.stringify(errorResponse, null, 2)}`,
580
+ options
581
+ );
582
+ this.errorResponse = errorResponse;
583
+ this.status = options?.status ?? 400;
584
+ }
585
+ };
586
+
587
+ // src/client-attestation/client-attestation-pop.ts
588
+ var import_utils7 = require("@openid4vc/utils");
589
+
590
+ // src/client-attestation/z-client-attestation.ts
591
+ var import_utils6 = require("@openid4vc/utils");
592
+ var import_zod7 = __toESM(require("zod"));
593
+ var zOauthClientAttestationHeader = import_zod7.default.literal("OAuth-Client-Attestation");
594
+ var oauthClientAttestationHeader = zOauthClientAttestationHeader.value;
595
+ var zClientAttestationJwtPayload = import_zod7.default.object({
596
+ ...zJwtPayload.shape,
597
+ iss: import_zod7.default.string(),
598
+ sub: import_zod7.default.string(),
599
+ exp: import_utils6.zInteger,
600
+ cnf: import_zod7.default.object({
601
+ jwk: zJwk
602
+ }).passthrough(),
603
+ // OID4VCI Wallet Attestation Extensions
604
+ wallet_name: import_zod7.default.string().optional(),
605
+ wallet_link: import_zod7.default.string().url().optional()
606
+ }).passthrough();
607
+ var zClientAttestationJwtHeader = import_zod7.default.object({
608
+ ...zJwtHeader.shape,
609
+ typ: import_zod7.default.literal("oauth-client-attestation+jwt")
610
+ }).passthrough();
611
+ var zOauthClientAttestationPopHeader = import_zod7.default.literal("OAuth-Client-Attestation-PoP");
612
+ var oauthClientAttestationPopHeader = zOauthClientAttestationPopHeader.value;
613
+ var zClientAttestationPopJwtPayload = import_zod7.default.object({
614
+ ...zJwtPayload.shape,
615
+ iss: import_zod7.default.string(),
616
+ exp: import_utils6.zInteger,
617
+ aud: import_utils6.zHttpsUrl,
618
+ jti: import_zod7.default.string(),
619
+ nonce: import_zod7.default.optional(import_zod7.default.string())
620
+ }).passthrough();
621
+ var zClientAttestationPopJwtHeader = import_zod7.default.object({
622
+ ...zJwtHeader.shape,
623
+ typ: import_zod7.default.literal("oauth-client-attestation-pop+jwt")
624
+ }).passthrough();
625
+
626
+ // src/client-attestation/client-attestation-pop.ts
627
+ async function verifyClientAttestationPopJwt(options) {
628
+ const { header, payload } = decodeJwt({
629
+ jwt: options.clientAttestationPopJwt,
630
+ headerSchema: zClientAttestationPopJwtHeader,
631
+ payloadSchema: zClientAttestationPopJwtPayload
632
+ });
633
+ if (payload.iss !== options.clientAttestation.payload.sub) {
634
+ throw new Oauth2Error(
635
+ `Client Attestation Pop jwt contains 'iss' (client_id) value '${payload.iss}', but expected 'sub' value from client attestation '${options.clientAttestation.payload.sub}'`
636
+ );
637
+ }
638
+ if (payload.aud !== options.authorizationServer) {
639
+ throw new Oauth2Error(
640
+ `Client Attestation Pop jwt contains 'aud' value '${payload.aud}', but expected authorization server identifier '${options.authorizationServer}'`
641
+ );
642
+ }
643
+ const { signer } = await verifyJwt({
644
+ signer: {
645
+ alg: header.alg,
646
+ method: "jwk",
647
+ publicJwk: options.clientAttestation.payload.cnf.jwk
648
+ },
649
+ now: options.now,
650
+ header,
651
+ expectedNonce: options.expectedNonce,
652
+ payload,
653
+ compact: options.clientAttestationPopJwt,
654
+ verifyJwtCallback: options.callbacks.verifyJwt,
655
+ errorMessage: "client attestation pop jwt verification failed"
656
+ });
657
+ return {
658
+ header,
659
+ payload,
660
+ signer
661
+ };
662
+ }
663
+ async function createClientAttestationPopJwt(options) {
664
+ const clientAttestation = decodeJwt({
665
+ jwt: options.clientAttestation,
666
+ headerSchema: zClientAttestationJwtHeader,
667
+ payloadSchema: zClientAttestationJwtPayload
668
+ });
669
+ const signer = options.signer ?? {
670
+ method: "jwk",
671
+ alg: clientAttestation.header.alg,
672
+ publicJwk: clientAttestation.payload.cnf.jwk
673
+ };
674
+ const header = (0, import_utils7.parseWithErrorHandling)(zClientAttestationPopJwtHeader, {
675
+ typ: "oauth-client-attestation-pop+jwt",
676
+ alg: signer.alg
677
+ });
678
+ const expiresAt = options.expiresAt ?? (0, import_utils7.addSecondsToDate)(options.issuedAt ?? /* @__PURE__ */ new Date(), 1 * 60);
679
+ const payload = (0, import_utils7.parseWithErrorHandling)(zClientAttestationPopJwtPayload, {
680
+ aud: options.authorizationServer,
681
+ iss: clientAttestation.payload.sub,
682
+ iat: (0, import_utils7.dateToSeconds)(options.issuedAt),
683
+ exp: (0, import_utils7.dateToSeconds)(expiresAt),
684
+ jti: (0, import_utils7.encodeToBase64Url)(await options.callbacks.generateRandom(32)),
685
+ nonce: options.nonce,
686
+ ...options.additionalPayload
687
+ });
688
+ const { jwt } = await options.callbacks.signJwt(signer, {
689
+ header,
690
+ payload
691
+ });
692
+ return jwt;
693
+ }
694
+
695
+ // src/client-attestation/clent-attestation.ts
696
+ async function verifyClientAttestationJwt(options) {
697
+ const { header, payload } = decodeJwt({
698
+ jwt: options.clientAttestationJwt,
699
+ headerSchema: zClientAttestationJwtHeader,
700
+ payloadSchema: zClientAttestationJwtPayload
701
+ });
702
+ const { signer } = await verifyJwt({
703
+ signer: jwtSignerFromJwt({ header, payload }),
704
+ now: options.now,
705
+ header,
706
+ payload,
707
+ compact: options.clientAttestationJwt,
708
+ verifyJwtCallback: options.callbacks.verifyJwt,
709
+ errorMessage: "client attestation jwt verification failed"
710
+ });
711
+ return {
712
+ header,
713
+ payload,
714
+ signer
715
+ };
716
+ }
717
+ async function createClientAttestationJwt(options) {
718
+ const header = (0, import_utils8.parseWithErrorHandling)(zClientAttestationJwtHeader, {
719
+ typ: "oauth-client-attestation+jwt",
720
+ ...jwtHeaderFromJwtSigner(options.signer)
721
+ });
722
+ const payload = (0, import_utils8.parseWithErrorHandling)(zClientAttestationJwtPayload, {
723
+ iss: options.issuer,
724
+ iat: (0, import_utils8.dateToSeconds)(options.issuedAt),
725
+ exp: (0, import_utils8.dateToSeconds)(options.expiresAt),
726
+ sub: options.clientId,
727
+ cnf: options.confirmation,
728
+ ...options.additionalPayload
729
+ });
730
+ const { jwt } = await options.callbacks.signJwt(options.signer, {
731
+ header,
732
+ payload
733
+ });
734
+ return jwt;
735
+ }
736
+ function extractClientAttestationJwtsFromHeaders(headers) {
737
+ const clientAttestationHeader = headers.get(oauthClientAttestationHeader);
738
+ const clientAttestationPopHeader = headers.get(oauthClientAttestationPopHeader);
739
+ if (!clientAttestationHeader && !clientAttestationPopHeader) {
740
+ return { valid: true };
741
+ }
742
+ if (!clientAttestationHeader || !clientAttestationPopHeader) {
743
+ return { valid: false };
744
+ }
745
+ if (!zCompactJwt.safeParse(clientAttestationHeader).success || !zCompactJwt.safeParse(clientAttestationPopHeader).success) {
746
+ return { valid: false };
747
+ }
748
+ return {
749
+ valid: true,
750
+ clientAttestationPopHeader,
751
+ clientAttestationHeader
752
+ };
753
+ }
754
+ async function verifyClientAttestation({
755
+ authorizationServer,
756
+ clientAttestationJwt,
757
+ clientAttestationPopJwt,
758
+ callbacks,
759
+ now
760
+ }) {
761
+ try {
762
+ const clientAttestation = await verifyClientAttestationJwt({
763
+ callbacks,
764
+ clientAttestationJwt,
765
+ now
766
+ });
767
+ const clientAttestationPop = await verifyClientAttestationPopJwt({
768
+ callbacks,
769
+ authorizationServer,
770
+ clientAttestation,
771
+ clientAttestationPopJwt,
772
+ now
773
+ });
774
+ return {
775
+ clientAttestation,
776
+ clientAttestationPop
777
+ };
778
+ } catch (error) {
779
+ if (error instanceof Oauth2Error) {
780
+ throw new Oauth2ServerErrorResponseError(
781
+ {
782
+ error: "invalid_client" /* InvalidClient */,
783
+ error_description: `Error verifying client attestation. ${error.message}`
784
+ },
785
+ {
786
+ status: 401,
787
+ cause: error
788
+ }
789
+ );
790
+ }
791
+ throw new Oauth2ServerErrorResponseError(
792
+ {
793
+ error: "server_error" /* ServerError */,
794
+ error_description: "Error during verification of client attestation jwt"
795
+ },
796
+ {
797
+ status: 500,
798
+ cause: error,
799
+ internalMessage: "Unknown error thrown during verification of client attestation jwt"
800
+ }
801
+ );
802
+ }
803
+ }
804
+
504
805
  // src/index.ts
505
- var import_utils43 = require("@openid4vc/utils");
806
+ var import_utils46 = require("@openid4vc/utils");
506
807
 
507
808
  // src/error/Oauth2ClientErrorResponseError.ts
508
809
  var Oauth2ClientErrorResponseError = class extends Oauth2Error {
@@ -522,16 +823,8 @@ var Oauth2ClientAuthorizationChallengeError = class extends Oauth2ClientErrorRes
522
823
  }
523
824
  };
524
825
 
525
- // src/error/Oauth2JwtVerificationError.ts
526
- var Oauth2JwtVerificationError = class extends Oauth2Error {
527
- constructor(message, options) {
528
- const errorMessage = message ?? "Error verifiying jwt.";
529
- super(errorMessage, options);
530
- }
531
- };
532
-
533
826
  // src/error/Oauth2ResourceUnauthorizedError.ts
534
- var import_utils5 = require("@openid4vc/utils");
827
+ var import_utils9 = require("@openid4vc/utils");
535
828
  var Oauth2ResourceUnauthorizedError = class _Oauth2ResourceUnauthorizedError extends Oauth2Error {
536
829
  constructor(internalMessage, wwwAuthenticateHeaders) {
537
830
  super(`${internalMessage}
@@ -539,7 +832,7 @@ ${JSON.stringify(wwwAuthenticateHeaders, null, 2)}`);
539
832
  this.wwwAuthenticateHeaders = Array.isArray(wwwAuthenticateHeaders) ? wwwAuthenticateHeaders : [wwwAuthenticateHeaders];
540
833
  }
541
834
  static fromHeaderValue(value) {
542
- const headers = (0, import_utils5.parseWwwAuthenticateHeader)(value);
835
+ const headers = (0, import_utils9.parseWwwAuthenticateHeader)(value);
543
836
  return new _Oauth2ResourceUnauthorizedError(
544
837
  void 0,
545
838
  headers.map(
@@ -554,7 +847,7 @@ ${JSON.stringify(wwwAuthenticateHeaders, null, 2)}`);
554
847
  );
555
848
  }
556
849
  toHeaderValue() {
557
- return (0, import_utils5.encodeWwwAuthenticateHeader)(
850
+ return (0, import_utils9.encodeWwwAuthenticateHeader)(
558
851
  this.wwwAuthenticateHeaders.map((header) => ({
559
852
  scheme: header.scheme,
560
853
  payload: {
@@ -568,97 +861,86 @@ ${JSON.stringify(wwwAuthenticateHeaders, null, 2)}`);
568
861
  }
569
862
  };
570
863
 
571
- // src/error/Oauth2ServerErrorResponseError.ts
572
- var Oauth2ServerErrorResponseError = class extends Oauth2Error {
573
- constructor(errorResponse, options) {
574
- super(
575
- `${options?.internalMessage ?? errorResponse.error_description}
576
- ${JSON.stringify(errorResponse, null, 2)}`,
577
- options
578
- );
579
- this.errorResponse = errorResponse;
580
- this.status = options?.status ?? 400;
581
- }
582
- };
583
-
584
864
  // src/metadata/authorization-server/authorization-server-metadata.ts
585
- var import_utils9 = require("@openid4vc/utils");
865
+ var import_utils13 = require("@openid4vc/utils");
586
866
 
587
867
  // src/metadata/fetch-well-known-metadata.ts
588
- var import_utils6 = require("@openid4vc/utils");
589
- var import_utils7 = require("@openid4vc/utils");
868
+ var import_utils10 = require("@openid4vc/utils");
869
+ var import_utils11 = require("@openid4vc/utils");
590
870
 
591
- // ../utils/src/error/ValidationError.ts
592
- var import_zod7 = require("zod");
871
+ // ../utils/src/zod-error.ts
872
+ var import_zod8 = require("zod");
593
873
  var constants = {
594
874
  // biome-ignore lint/suspicious/noMisleadingCharacterClass: expected
595
875
  identifierRegex: /[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*/u,
596
876
  unionSeparator: ", or ",
597
877
  issueSeparator: "\n - "
598
878
  };
599
- var ValidationError = class extends Error {
600
- escapeQuotes(str) {
601
- return str.replace(/"/g, '\\"');
879
+ function escapeQuotes(str) {
880
+ return str.replace(/"/g, '\\"');
881
+ }
882
+ function joinPath(path) {
883
+ if (path.length === 1) {
884
+ return path[0].toString();
602
885
  }
603
- joinPath(path) {
604
- if (path.length === 1) {
605
- return path[0].toString();
886
+ return path.reduce((acc, item) => {
887
+ if (typeof item === "number") {
888
+ return `${acc}[${item.toString()}]`;
606
889
  }
607
- return path.reduce((acc, item) => {
608
- if (typeof item === "number") {
609
- return `${acc}[${item.toString()}]`;
610
- }
611
- if (item.includes('"')) {
612
- return `${acc}["${this.escapeQuotes(item)}"]`;
613
- }
614
- if (!constants.identifierRegex.test(item)) {
615
- return `${acc}["${item}"]`;
616
- }
617
- const separator = acc.length === 0 ? "" : ".";
618
- return acc + separator + item;
619
- }, "");
620
- }
621
- getMessageFromUnionErrors(unionErrors) {
622
- return unionErrors.reduce((acc, zodError) => {
623
- const newIssues = zodError.issues.map((issue) => this.getMessageFromZodIssue(issue)).join(constants.issueSeparator);
624
- if (!acc.includes(newIssues)) acc.push(newIssues);
625
- return acc;
626
- }, []).join(constants.unionSeparator);
627
- }
628
- getMessageFromZodIssue(issue) {
629
- if (issue.code === import_zod7.ZodIssueCode.invalid_union) {
630
- return this.getMessageFromUnionErrors(issue.unionErrors);
890
+ if (item.includes('"')) {
891
+ return `${acc}["${escapeQuotes(item)}"]`;
631
892
  }
632
- if (issue.code === import_zod7.ZodIssueCode.invalid_arguments) {
633
- return [issue.message, ...issue.argumentsError.issues.map((issue2) => this.getMessageFromZodIssue(issue2))].join(
634
- constants.issueSeparator
635
- );
893
+ if (!constants.identifierRegex.test(item)) {
894
+ return `${acc}["${item}"]`;
636
895
  }
637
- if (issue.code === import_zod7.ZodIssueCode.invalid_return_type) {
638
- return [issue.message, ...issue.returnTypeError.issues.map((issue2) => this.getMessageFromZodIssue(issue2))].join(
639
- constants.issueSeparator
640
- );
641
- }
642
- if (issue.path.length !== 0) {
643
- if (issue.path.length === 1) {
644
- const identifier = issue.path[0];
645
- if (typeof identifier === "number") {
646
- return `${issue.message} at index ${identifier}`;
647
- }
896
+ const separator = acc.length === 0 ? "" : ".";
897
+ return acc + separator + item;
898
+ }, "");
899
+ }
900
+ function getMessageFromZodIssue(issue) {
901
+ if (issue.code === import_zod8.ZodIssueCode.invalid_union) {
902
+ return getMessageFromUnionErrors(issue.unionErrors);
903
+ }
904
+ if (issue.code === import_zod8.ZodIssueCode.invalid_arguments) {
905
+ return [issue.message, ...issue.argumentsError.issues.map((issue2) => getMessageFromZodIssue(issue2))].join(
906
+ constants.issueSeparator
907
+ );
908
+ }
909
+ if (issue.code === import_zod8.ZodIssueCode.invalid_return_type) {
910
+ return [issue.message, ...issue.returnTypeError.issues.map((issue2) => getMessageFromZodIssue(issue2))].join(
911
+ constants.issueSeparator
912
+ );
913
+ }
914
+ if (issue.path.length !== 0) {
915
+ if (issue.path.length === 1) {
916
+ const identifier = issue.path[0];
917
+ if (typeof identifier === "number") {
918
+ return `${issue.message} at index ${identifier}`;
648
919
  }
649
- return `${issue.message} at "${this.joinPath(issue.path)}"`;
650
920
  }
651
- return issue.message;
652
- }
653
- formatError(error) {
654
- if (!error) return "";
655
- return error?.issues.map((issue) => this.getMessageFromZodIssue(issue)).join(constants.issueSeparator);
921
+ return `${issue.message} at "${joinPath(issue.path)}"`;
656
922
  }
923
+ return issue.message;
924
+ }
925
+ function getMessageFromUnionErrors(unionErrors) {
926
+ return unionErrors.reduce((acc, zodError) => {
927
+ const newIssues = zodError.issues.map((issue) => getMessageFromZodIssue(issue)).join(constants.issueSeparator);
928
+ if (!acc.includes(newIssues)) acc.push(newIssues);
929
+ return acc;
930
+ }, []).join(constants.unionSeparator);
931
+ }
932
+ function formatZodError(error) {
933
+ if (!error) return "";
934
+ return ` - ${error?.issues.map((issue) => getMessageFromZodIssue(issue)).join(constants.issueSeparator)}`;
935
+ }
936
+
937
+ // ../utils/src/error/ValidationError.ts
938
+ var ValidationError = class extends Error {
657
939
  constructor(message, zodError) {
658
940
  super(message);
659
- const formattedError = this.formatError(zodError);
941
+ const formattedError = formatZodError(zodError);
660
942
  this.message = `${message}
661
- - ${formattedError}`;
943
+ ${formattedError}`;
662
944
  Object.defineProperty(this, "zodError", {
663
945
  value: zodError,
664
946
  writable: false,
@@ -669,13 +951,13 @@ var ValidationError = class extends Error {
669
951
 
670
952
  // src/metadata/fetch-well-known-metadata.ts
671
953
  async function fetchWellKnownMetadata(wellKnownMetadataUrl, schema, fetch) {
672
- const fetcher = (0, import_utils6.createZodFetcher)(fetch);
673
- const { result, response } = await fetcher(schema, import_utils6.ContentType.Json, wellKnownMetadataUrl);
954
+ const fetcher = (0, import_utils10.createZodFetcher)(fetch);
955
+ const { result, response } = await fetcher(schema, import_utils10.ContentType.Json, wellKnownMetadataUrl);
674
956
  if (response.status === 404) {
675
957
  return null;
676
958
  }
677
959
  if (!response.ok) {
678
- throw new import_utils7.InvalidFetchResponseError(
960
+ throw new import_utils11.InvalidFetchResponseError(
679
961
  `Fetching well known metadata from '${wellKnownMetadataUrl}' resulted in an unsuccessfull response with status '${response.status}'.`,
680
962
  await response.clone().text(),
681
963
  response
@@ -688,31 +970,40 @@ async function fetchWellKnownMetadata(wellKnownMetadataUrl, schema, fetch) {
688
970
  }
689
971
 
690
972
  // src/metadata/authorization-server/z-authorization-server-metadata.ts
691
- var import_utils8 = require("@openid4vc/utils");
692
- var import_zod8 = __toESM(require("zod"));
693
- var zAuthorizationServerMetadata = import_zod8.default.object({
694
- issuer: import_utils8.zHttpsUrl,
695
- token_endpoint: import_utils8.zHttpsUrl,
696
- token_endpoint_auth_methods_supported: import_zod8.default.optional(import_zod8.default.array(import_zod8.default.string())),
697
- authorization_endpoint: import_zod8.default.optional(import_utils8.zHttpsUrl),
698
- jwks_uri: import_zod8.default.optional(import_utils8.zHttpsUrl),
973
+ var import_utils12 = require("@openid4vc/utils");
974
+ var import_zod9 = __toESM(require("zod"));
975
+ var knownClientAuthenticationMethod = import_zod9.default.enum([
976
+ "client_secret_basic",
977
+ "client_secret_post",
978
+ "attest_jwt_client_auth",
979
+ "client_secret_jwt",
980
+ "private_key_jwt"
981
+ ]);
982
+ var zAuthorizationServerMetadata = import_zod9.default.object({
983
+ issuer: import_utils12.zHttpsUrl,
984
+ token_endpoint: import_utils12.zHttpsUrl,
985
+ token_endpoint_auth_methods_supported: import_zod9.default.optional(import_zod9.default.array(import_zod9.default.union([knownClientAuthenticationMethod, import_zod9.default.string()]))),
986
+ authorization_endpoint: import_zod9.default.optional(import_utils12.zHttpsUrl),
987
+ jwks_uri: import_zod9.default.optional(import_utils12.zHttpsUrl),
699
988
  // RFC7636
700
- code_challenge_methods_supported: import_zod8.default.optional(import_zod8.default.array(import_zod8.default.string())),
989
+ code_challenge_methods_supported: import_zod9.default.optional(import_zod9.default.array(import_zod9.default.string())),
701
990
  // RFC9449
702
- dpop_signing_alg_values_supported: import_zod8.default.optional(import_zod8.default.array(import_zod8.default.string())),
991
+ dpop_signing_alg_values_supported: import_zod9.default.optional(import_zod9.default.array(import_zod9.default.string())),
703
992
  // RFC9126
704
- require_pushed_authorization_requests: import_zod8.default.optional(import_zod8.default.boolean()),
705
- pushed_authorization_request_endpoint: import_zod8.default.optional(import_utils8.zHttpsUrl),
993
+ require_pushed_authorization_requests: import_zod9.default.optional(import_zod9.default.boolean()),
994
+ pushed_authorization_request_endpoint: import_zod9.default.optional(import_utils12.zHttpsUrl),
706
995
  // RFC9068
707
- introspection_endpoint: import_zod8.default.optional(import_utils8.zHttpsUrl),
708
- introspection_endpoint_auth_methods_supported: import_zod8.default.optional(
709
- import_zod8.default.array(import_zod8.default.union([import_zod8.default.literal("client_secret_jwt"), import_zod8.default.literal("private_key_jwt"), import_zod8.default.string()]))
996
+ introspection_endpoint: import_zod9.default.optional(import_utils12.zHttpsUrl),
997
+ introspection_endpoint_auth_methods_supported: import_zod9.default.optional(
998
+ import_zod9.default.array(import_zod9.default.union([knownClientAuthenticationMethod, import_zod9.default.string()]))
710
999
  ),
711
- introspection_endpoint_auth_signing_alg_values_supported: import_zod8.default.optional(import_zod8.default.array(zAlgValueNotNone)),
1000
+ introspection_endpoint_auth_signing_alg_values_supported: import_zod9.default.optional(import_zod9.default.array(zAlgValueNotNone)),
712
1001
  // FiPA (no RFC yet)
713
- authorization_challenge_endpoint: import_zod8.default.optional(import_utils8.zHttpsUrl),
1002
+ authorization_challenge_endpoint: import_zod9.default.optional(import_utils12.zHttpsUrl),
714
1003
  // From OpenID4VCI specification
715
- pre_authorized_grant_anonymous_access_supported: import_zod8.default.optional(import_zod8.default.boolean())
1004
+ pre_authorized_grant_anonymous_access_supported: import_zod9.default.optional(import_zod9.default.boolean()),
1005
+ // Attestation Based Client Auth (draft 5)
1006
+ client_attestation_pop_nonce_required: import_zod9.default.boolean().optional()
716
1007
  }).passthrough().refine(
717
1008
  ({
718
1009
  introspection_endpoint_auth_methods_supported: methodsSupported,
@@ -729,9 +1020,9 @@ var zAuthorizationServerMetadata = import_zod8.default.object({
729
1020
  var wellKnownAuthorizationServerSuffix = ".well-known/oauth-authorization-server";
730
1021
  var wellKnownOpenIdConfigurationServerSuffix = ".well-known/openid-configuration";
731
1022
  async function fetchAuthorizationServerMetadata(issuer, fetch) {
732
- const openIdConfigurationWellKnownMetadataUrl = (0, import_utils9.joinUriParts)(issuer, [wellKnownOpenIdConfigurationServerSuffix]);
733
- const parsedIssuerUrl = new import_utils9.URL(issuer);
734
- const authorizationServerWellKnownMetadataUrl = (0, import_utils9.joinUriParts)(parsedIssuerUrl.origin, [
1023
+ const openIdConfigurationWellKnownMetadataUrl = (0, import_utils13.joinUriParts)(issuer, [wellKnownOpenIdConfigurationServerSuffix]);
1024
+ const parsedIssuerUrl = new import_utils13.URL(issuer);
1025
+ const authorizationServerWellKnownMetadataUrl = (0, import_utils13.joinUriParts)(parsedIssuerUrl.origin, [
735
1026
  wellKnownAuthorizationServerSuffix,
736
1027
  parsedIssuerUrl.pathname
737
1028
  ]);
@@ -748,7 +1039,7 @@ async function fetchAuthorizationServerMetadata(issuer, fetch) {
748
1039
  }
749
1040
  return authorizationServerResult;
750
1041
  }
751
- const nonCompliantAuthorizationServerWellKnownMetadataUrl = (0, import_utils9.joinUriParts)(issuer, [wellKnownAuthorizationServerSuffix]);
1042
+ const nonCompliantAuthorizationServerWellKnownMetadataUrl = (0, import_utils13.joinUriParts)(issuer, [wellKnownAuthorizationServerSuffix]);
752
1043
  const alternativeAuthorizationServerResult = nonCompliantAuthorizationServerWellKnownMetadataUrl !== authorizationServerWellKnownMetadataUrl ? await fetchWellKnownMetadata(
753
1044
  nonCompliantAuthorizationServerWellKnownMetadataUrl,
754
1045
  zAuthorizationServerMetadata,
@@ -790,13 +1081,13 @@ function getAuthorizationServerMetadataFromList(authorizationServersMetadata, is
790
1081
  }
791
1082
 
792
1083
  // src/metadata/fetch-jwks-uri.ts
793
- var import_utils10 = require("@openid4vc/utils");
794
- var import_utils11 = require("@openid4vc/utils");
1084
+ var import_utils14 = require("@openid4vc/utils");
1085
+ var import_utils15 = require("@openid4vc/utils");
795
1086
  async function fetchJwks(jwksUrl, fetch) {
796
- const fetcher = (0, import_utils10.createZodFetcher)(fetch);
797
- const { result, response } = await fetcher(zJwkSet, import_utils10.ContentType.JwkSet, jwksUrl);
1087
+ const fetcher = (0, import_utils14.createZodFetcher)(fetch);
1088
+ const { result, response } = await fetcher(zJwkSet, import_utils14.ContentType.JwkSet, jwksUrl);
798
1089
  if (!response.ok) {
799
- throw new import_utils11.InvalidFetchResponseError(
1090
+ throw new import_utils15.InvalidFetchResponseError(
800
1091
  `Fetching JWKs from jwks_uri '${jwksUrl}' resulted in an unsuccessfull response with status code '${response.status}'.`,
801
1092
  await response.clone().text(),
802
1093
  response
@@ -808,78 +1099,25 @@ async function fetchJwks(jwksUrl, fetch) {
808
1099
  return result.data;
809
1100
  }
810
1101
 
811
- // src/common/jwt/verify-jwt.ts
812
- var import_utils12 = require("@openid4vc/utils");
813
- async function verifyJwt(options) {
814
- const errorMessage = options.errorMessage ?? "Error during verification of jwt.";
815
- let signerJwk;
816
- try {
817
- const result = await options.verifyJwtCallback(options.signer, {
818
- header: options.header,
819
- payload: options.payload,
820
- compact: options.compact
821
- });
822
- if (!result.verified) throw new Oauth2JwtVerificationError(errorMessage);
823
- signerJwk = result.signerJwk;
824
- } catch (error) {
825
- if (error instanceof Oauth2JwtVerificationError) throw error;
826
- throw new Oauth2JwtVerificationError(errorMessage, { cause: error });
827
- }
828
- const nowInSeconds = (0, import_utils12.dateToSeconds)(options.now ?? /* @__PURE__ */ new Date());
829
- const skewInSeconds = options.allowedSkewInSeconds ?? 0;
830
- const timeBasedValidation = options.skipTimeBasedValidation !== void 0 ? !options.skipTimeBasedValidation : true;
831
- if (timeBasedValidation && options.payload.nbf && nowInSeconds < options.payload.nbf - skewInSeconds) {
832
- throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'nbf' is in the future`);
833
- }
834
- if (timeBasedValidation && options.payload.exp && nowInSeconds > options.payload.exp + skewInSeconds) {
835
- throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'exp' is in the past`);
836
- }
837
- if (options.expectedAudience && options.expectedAudience !== options.payload.aud) {
838
- throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'aud' does not match expected value.`);
839
- }
840
- if (options.expectedIssuer && options.expectedIssuer !== options.payload.iss) {
841
- throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'iss' does not match expected value.`);
842
- }
843
- if (options.expectedNonce && options.expectedNonce !== options.payload.nonce) {
844
- throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'nonce' does not match expected value.`);
845
- }
846
- if (options.expectedSubject && options.expectedSubject !== options.payload.sub) {
847
- throw new Oauth2JwtVerificationError(`${errorMessage} jwt 'sub' does not match expected value.`);
848
- }
849
- if (options.requiredClaims) {
850
- for (const claim of options.requiredClaims) {
851
- if (!options.payload[claim]) {
852
- throw new Oauth2JwtVerificationError(`${errorMessage} jwt '${claim}' is missing.`);
853
- }
854
- }
855
- }
856
- return {
857
- signer: {
858
- ...options.signer,
859
- publicJwk: signerJwk
860
- }
861
- };
862
- }
863
-
864
1102
  // src/access-token/z-access-token-jwt.ts
865
- var import_utils13 = require("@openid4vc/utils");
866
- var import_zod9 = __toESM(require("zod"));
867
- var zAccessTokenProfileJwtHeader = import_zod9.default.object({
1103
+ var import_utils16 = require("@openid4vc/utils");
1104
+ var import_zod10 = __toESM(require("zod"));
1105
+ var zAccessTokenProfileJwtHeader = import_zod10.default.object({
868
1106
  ...zJwtHeader.shape,
869
- typ: import_zod9.default.enum(["application/at+jwt", "at+jwt"])
1107
+ typ: import_zod10.default.enum(["application/at+jwt", "at+jwt"])
870
1108
  }).passthrough();
871
- var zAccessTokenProfileJwtPayload = import_zod9.default.object({
1109
+ var zAccessTokenProfileJwtPayload = import_zod10.default.object({
872
1110
  ...zJwtPayload.shape,
873
- iss: import_zod9.default.string(),
874
- exp: import_utils13.zInteger,
875
- iat: import_utils13.zInteger,
876
- aud: import_zod9.default.string(),
877
- sub: import_zod9.default.string(),
1111
+ iss: import_zod10.default.string(),
1112
+ exp: import_utils16.zInteger,
1113
+ iat: import_utils16.zInteger,
1114
+ aud: import_zod10.default.string(),
1115
+ sub: import_zod10.default.string(),
878
1116
  // REQUIRED according to RFC 9068, but OpenID4VCI allows anonymous access
879
- client_id: import_zod9.default.optional(import_zod9.default.string()),
880
- jti: import_zod9.default.string(),
1117
+ client_id: import_zod10.default.optional(import_zod10.default.string()),
1118
+ jti: import_zod10.default.string(),
881
1119
  // SHOULD be included in the authorization request contained it
882
- scope: import_zod9.default.optional(import_zod9.default.string())
1120
+ scope: import_zod10.default.optional(import_zod10.default.string())
883
1121
  }).passthrough();
884
1122
 
885
1123
  // src/access-token/verify-access-token.ts
@@ -930,26 +1168,26 @@ async function verifyJwtProfileAccessToken(options) {
930
1168
  }
931
1169
 
932
1170
  // src/resource-request/make-resource-request.ts
933
- var import_utils16 = require("@openid4vc/utils");
1171
+ var import_utils19 = require("@openid4vc/utils");
934
1172
 
935
1173
  // src/dpop/dpop.ts
936
- var import_utils15 = require("@openid4vc/utils");
1174
+ var import_utils18 = require("@openid4vc/utils");
937
1175
 
938
1176
  // src/dpop/z-dpop.ts
939
- var import_utils14 = require("@openid4vc/utils");
940
- var import_zod10 = __toESM(require("zod"));
941
- var zDpopJwtPayload = import_zod10.default.object({
1177
+ var import_utils17 = require("@openid4vc/utils");
1178
+ var import_zod11 = __toESM(require("zod"));
1179
+ var zDpopJwtPayload = import_zod11.default.object({
942
1180
  ...zJwtPayload.shape,
943
- iat: import_utils14.zInteger,
944
- htu: import_utils14.zHttpsUrl,
945
- htm: import_utils14.zHttpMethod,
946
- jti: import_zod10.default.string(),
1181
+ iat: import_utils17.zInteger,
1182
+ htu: import_utils17.zHttpsUrl,
1183
+ htm: import_utils17.zHttpMethod,
1184
+ jti: import_zod11.default.string(),
947
1185
  // Only required when presenting in combination with access token
948
- ath: import_zod10.default.optional(import_zod10.default.string())
1186
+ ath: import_zod11.default.optional(import_zod11.default.string())
949
1187
  }).passthrough();
950
- var zDpopJwtHeader = import_zod10.default.object({
1188
+ var zDpopJwtHeader = import_zod11.default.object({
951
1189
  ...zJwtHeader.shape,
952
- typ: import_zod10.default.literal("dpop+jwt"),
1190
+ typ: import_zod11.default.literal("dpop+jwt"),
953
1191
  jwk: zJwk
954
1192
  }).passthrough();
955
1193
 
@@ -963,18 +1201,18 @@ async function createDpopHeadersForRequest(options) {
963
1201
  async function createDpopJwt(options) {
964
1202
  let ath = void 0;
965
1203
  if (options.accessToken) {
966
- ath = (0, import_utils15.encodeToBase64Url)(await options.callbacks.hash((0, import_utils15.decodeUtf8String)(options.accessToken), "sha-256" /* Sha256 */));
1204
+ ath = (0, import_utils18.encodeToBase64Url)(await options.callbacks.hash((0, import_utils18.decodeUtf8String)(options.accessToken), "sha-256" /* Sha256 */));
967
1205
  }
968
- const header = (0, import_utils15.parseWithErrorHandling)(zDpopJwtHeader, {
1206
+ const header = (0, import_utils18.parseWithErrorHandling)(zDpopJwtHeader, {
969
1207
  typ: "dpop+jwt",
970
1208
  jwk: options.signer.publicJwk,
971
1209
  alg: options.signer.alg
972
1210
  });
973
- const payload = (0, import_utils15.parseWithErrorHandling)(zDpopJwtPayload, {
1211
+ const payload = (0, import_utils18.parseWithErrorHandling)(zDpopJwtPayload, {
974
1212
  htu: htuFromRequestUrl(options.request.url),
975
- iat: (0, import_utils15.dateToSeconds)(options.issuedAt),
1213
+ iat: (0, import_utils18.dateToSeconds)(options.issuedAt),
976
1214
  htm: options.request.method,
977
- jti: (0, import_utils15.encodeToBase64Url)(await options.callbacks.generateRandom(32)),
1215
+ jti: (0, import_utils18.encodeToBase64Url)(await options.callbacks.generateRandom(32)),
978
1216
  ath,
979
1217
  nonce: options.nonce,
980
1218
  ...options.additionalPayload
@@ -986,78 +1224,89 @@ async function createDpopJwt(options) {
986
1224
  return jwt;
987
1225
  }
988
1226
  async function verifyDpopJwt(options) {
989
- const { header, payload } = decodeJwt({
990
- jwt: options.dpopJwt,
991
- headerSchema: zDpopJwtHeader,
992
- payloadSchema: zDpopJwtPayload
993
- });
994
- if (options.allowedSigningAlgs && !options.allowedSigningAlgs.includes(header.alg)) {
995
- throw new Oauth2Error(
996
- `dpop jwt uses alg value '${header.alg}' but allowed dpop signging alg values are ${options.allowedSigningAlgs.join(", ")}.`
997
- );
998
- }
999
- if (options.expectedNonce) {
1000
- if (!payload.nonce) {
1001
- throw new Oauth2Error(`Dpop jwt does not have a nonce value, but expected nonce value '${options.expectedNonce}'`);
1227
+ try {
1228
+ const { header, payload } = decodeJwt({
1229
+ jwt: options.dpopJwt,
1230
+ headerSchema: zDpopJwtHeader,
1231
+ payloadSchema: zDpopJwtPayload
1232
+ });
1233
+ if (options.allowedSigningAlgs && !options.allowedSigningAlgs.includes(header.alg)) {
1234
+ throw new Oauth2Error(
1235
+ `dpop jwt uses alg value '${header.alg}' but allowed dpop signging alg values are ${options.allowedSigningAlgs.join(", ")}.`
1236
+ );
1237
+ }
1238
+ if (options.expectedNonce) {
1239
+ if (!payload.nonce) {
1240
+ throw new Oauth2Error(
1241
+ `Dpop jwt does not have a nonce value, but expected nonce value '${options.expectedNonce}'`
1242
+ );
1243
+ }
1244
+ if (payload.nonce !== options.expectedNonce) {
1245
+ throw new Oauth2Error(
1246
+ `Dpop jwt contains nonce value '${payload.nonce}', but expected nonce value '${options.expectedNonce}'`
1247
+ );
1248
+ }
1002
1249
  }
1003
- if (payload.nonce !== options.expectedNonce) {
1250
+ if (options.request.method !== payload.htm) {
1004
1251
  throw new Oauth2Error(
1005
- `Dpop jwt contains nonce value '${payload.nonce}', but expected nonce value '${options.expectedNonce}'`
1252
+ `Dpop jwt contains htm value '${payload.htm}', but expected htm value '${options.request.method}'`
1006
1253
  );
1007
1254
  }
1008
- }
1009
- if (options.request.method !== payload.htm) {
1010
- throw new Oauth2Error(
1011
- `Dpop jwt contains htm value '${payload.htm}', but expected htm value '${options.request.method}'`
1012
- );
1013
- }
1014
- const expectedHtu = htuFromRequestUrl(options.request.url);
1015
- if (expectedHtu !== payload.htu) {
1016
- throw new Oauth2Error(`Dpop jwt contains htu value '${payload.htu}', but expected htu value '${expectedHtu}'.`);
1017
- }
1018
- if (options.accessToken) {
1019
- const expectedAth = (0, import_utils15.encodeToBase64Url)(
1020
- await options.callbacks.hash((0, import_utils15.decodeUtf8String)(options.accessToken), "sha-256" /* Sha256 */)
1021
- );
1022
- if (!payload.ath) {
1023
- throw new Oauth2Error(`Dpop jwt does not have a ath value, but expected ath value '${expectedAth}'.`);
1255
+ const expectedHtu = htuFromRequestUrl(options.request.url);
1256
+ if (expectedHtu !== payload.htu) {
1257
+ throw new Oauth2Error(`Dpop jwt contains htu value '${payload.htu}', but expected htu value '${expectedHtu}'.`);
1024
1258
  }
1025
- if (payload.ath !== expectedAth) {
1026
- throw new Oauth2Error(`Dpop jwt contains ath value '${payload.ath}', but expected ath value '${expectedAth}'.`);
1259
+ if (options.accessToken) {
1260
+ const expectedAth = (0, import_utils18.encodeToBase64Url)(
1261
+ await options.callbacks.hash((0, import_utils18.decodeUtf8String)(options.accessToken), "sha-256" /* Sha256 */)
1262
+ );
1263
+ if (!payload.ath) {
1264
+ throw new Oauth2Error(`Dpop jwt does not have a ath value, but expected ath value '${expectedAth}'.`);
1265
+ }
1266
+ if (payload.ath !== expectedAth) {
1267
+ throw new Oauth2Error(`Dpop jwt contains ath value '${payload.ath}', but expected ath value '${expectedAth}'.`);
1268
+ }
1027
1269
  }
1028
- }
1029
- if (options.expectedJwkThumbprint) {
1030
- const jwkThumprint = await calculateJwkThumbprint({
1270
+ const jwkThumbprint = await calculateJwkThumbprint({
1031
1271
  hashAlgorithm: "sha-256" /* Sha256 */,
1032
1272
  hashCallback: options.callbacks.hash,
1033
1273
  jwk: header.jwk
1034
1274
  });
1035
- if (options.expectedJwkThumbprint !== jwkThumprint) {
1275
+ if (options.expectedJwkThumbprint && options.expectedJwkThumbprint !== jwkThumbprint) {
1036
1276
  throw new Oauth2Error(
1037
- `Dpop is signed with jwk with thumbprint value '${jwkThumprint}', but expect jwk thumbprint value '${options.expectedJwkThumbprint}'`
1277
+ `Dpop is signed with jwk with thumbprint value '${jwkThumbprint}', but expect jwk thumbprint value '${options.expectedJwkThumbprint}'`
1038
1278
  );
1039
1279
  }
1280
+ await verifyJwt({
1281
+ signer: {
1282
+ alg: header.alg,
1283
+ method: "jwk",
1284
+ publicJwk: header.jwk
1285
+ },
1286
+ now: options.now,
1287
+ header,
1288
+ payload,
1289
+ compact: options.dpopJwt,
1290
+ verifyJwtCallback: options.callbacks.verifyJwt,
1291
+ errorMessage: "dpop jwt verification failed"
1292
+ });
1293
+ return {
1294
+ header,
1295
+ payload,
1296
+ jwkThumbprint
1297
+ };
1298
+ } catch (error) {
1299
+ if (error instanceof Oauth2Error) {
1300
+ throw new Oauth2ServerErrorResponseError({
1301
+ error: "invalid_dpop_proof" /* InvalidDpopProof */,
1302
+ error_description: error.message
1303
+ });
1304
+ }
1305
+ throw error;
1040
1306
  }
1041
- await verifyJwt({
1042
- signer: {
1043
- alg: header.alg,
1044
- method: "jwk",
1045
- publicJwk: header.jwk
1046
- },
1047
- now: options.now,
1048
- header,
1049
- payload,
1050
- compact: options.dpopJwt,
1051
- verifyJwtCallback: options.callbacks.verifyJwt,
1052
- errorMessage: "dpop jwt verification failed"
1053
- });
1054
- return {
1055
- header,
1056
- payload
1057
- };
1058
1307
  }
1059
1308
  function htuFromRequestUrl(requestUrl) {
1060
- const htu = new import_utils15.URL(requestUrl);
1309
+ const htu = new import_utils18.URL(requestUrl);
1061
1310
  htu.search = "";
1062
1311
  htu.hash = "";
1063
1312
  return htu.toString();
@@ -1067,10 +1316,13 @@ function extractDpopNonceFromHeaders(headers) {
1067
1316
  }
1068
1317
  function extractDpopJwtFromHeaders(headers) {
1069
1318
  const dpopJwt = headers.get("DPoP");
1070
- if (dpopJwt && (typeof dpopJwt !== "string" || dpopJwt.includes(","))) {
1319
+ if (!dpopJwt) {
1320
+ return { valid: true };
1321
+ }
1322
+ if (!zCompactJwt.safeParse(dpopJwt).success) {
1071
1323
  return { valid: false };
1072
1324
  }
1073
- return { valid: true, dpopJwt: dpopJwt ?? void 0 };
1325
+ return { valid: true, dpopJwt };
1074
1326
  }
1075
1327
 
1076
1328
  // src/dpop/dpop-retry.ts
@@ -1142,7 +1394,7 @@ async function resourceRequest(options) {
1142
1394
  nonce: options.dpop.nonce,
1143
1395
  accessToken: options.accessToken
1144
1396
  }) : void 0;
1145
- const response = await (0, import_utils16.createFetcher)(options.callbacks.fetch)(options.url, {
1397
+ const response = await (0, import_utils19.createFetcher)(options.callbacks.fetch)(options.url, {
1146
1398
  ...options.requestOptions,
1147
1399
  headers: {
1148
1400
  ...options.requestOptions.headers,
@@ -1189,40 +1441,40 @@ async function resourceRequest(options) {
1189
1441
  }
1190
1442
 
1191
1443
  // src/resource-request/verify-resource-request.ts
1192
- var import_utils21 = require("@openid4vc/utils");
1444
+ var import_utils24 = require("@openid4vc/utils");
1193
1445
 
1194
1446
  // src/access-token/introspect-token.ts
1195
- var import_utils18 = require("@openid4vc/utils");
1196
- var import_utils19 = require("@openid4vc/utils");
1197
- var import_utils20 = require("@openid4vc/utils");
1447
+ var import_utils21 = require("@openid4vc/utils");
1448
+ var import_utils22 = require("@openid4vc/utils");
1449
+ var import_utils23 = require("@openid4vc/utils");
1198
1450
 
1199
1451
  // src/access-token/z-token-introspection.ts
1200
- var import_utils17 = require("@openid4vc/utils");
1201
- var import_zod11 = __toESM(require("zod"));
1202
- var zTokenIntrospectionRequest = import_zod11.default.object({
1203
- token: import_zod11.default.string(),
1204
- token_type_hint: import_zod11.default.optional(import_zod11.default.string())
1452
+ var import_utils20 = require("@openid4vc/utils");
1453
+ var import_zod12 = __toESM(require("zod"));
1454
+ var zTokenIntrospectionRequest = import_zod12.default.object({
1455
+ token: import_zod12.default.string(),
1456
+ token_type_hint: import_zod12.default.optional(import_zod12.default.string())
1205
1457
  }).passthrough();
1206
- var zTokenIntrospectionResponse = import_zod11.default.object({
1207
- active: import_zod11.default.boolean(),
1208
- scope: import_zod11.default.optional(import_zod11.default.string()),
1209
- client_id: import_zod11.default.optional(import_zod11.default.string()),
1210
- username: import_zod11.default.optional(import_zod11.default.string()),
1211
- token_type: import_zod11.default.optional(import_zod11.default.string()),
1212
- exp: import_zod11.default.optional(import_utils17.zInteger),
1213
- iat: import_zod11.default.optional(import_utils17.zInteger),
1214
- nbf: import_zod11.default.optional(import_utils17.zInteger),
1215
- sub: import_zod11.default.optional(import_zod11.default.string()),
1216
- aud: import_zod11.default.optional(import_zod11.default.string()),
1217
- iss: import_zod11.default.optional(import_zod11.default.string()),
1218
- jti: import_zod11.default.optional(import_zod11.default.string()),
1219
- cnf: import_zod11.default.optional(zJwtConfirmationPayload)
1458
+ var zTokenIntrospectionResponse = import_zod12.default.object({
1459
+ active: import_zod12.default.boolean(),
1460
+ scope: import_zod12.default.optional(import_zod12.default.string()),
1461
+ client_id: import_zod12.default.optional(import_zod12.default.string()),
1462
+ username: import_zod12.default.optional(import_zod12.default.string()),
1463
+ token_type: import_zod12.default.optional(import_zod12.default.string()),
1464
+ exp: import_zod12.default.optional(import_utils20.zInteger),
1465
+ iat: import_zod12.default.optional(import_utils20.zInteger),
1466
+ nbf: import_zod12.default.optional(import_utils20.zInteger),
1467
+ sub: import_zod12.default.optional(import_zod12.default.string()),
1468
+ aud: import_zod12.default.optional(import_zod12.default.string()),
1469
+ iss: import_zod12.default.optional(import_zod12.default.string()),
1470
+ jti: import_zod12.default.optional(import_zod12.default.string()),
1471
+ cnf: import_zod12.default.optional(zJwtConfirmationPayload)
1220
1472
  }).passthrough();
1221
1473
 
1222
1474
  // src/access-token/introspect-token.ts
1223
1475
  async function introspectToken(options) {
1224
- const fetchWithZod = (0, import_utils18.createZodFetcher)(options.callbacks.fetch);
1225
- const introspectionRequest = (0, import_utils18.parseWithErrorHandling)(zTokenIntrospectionRequest, {
1476
+ const fetchWithZod = (0, import_utils21.createZodFetcher)(options.callbacks.fetch);
1477
+ const introspectionRequest = (0, import_utils21.parseWithErrorHandling)(zTokenIntrospectionRequest, {
1226
1478
  token: options.token,
1227
1479
  token_type_hint: options.tokenTypeHint,
1228
1480
  ...options.additionalPayload
@@ -1231,29 +1483,29 @@ async function introspectToken(options) {
1231
1483
  if (!introspectionEndpoint) {
1232
1484
  throw new Oauth2Error(`Missing required 'introspection_endpoint' parameter in authorization server metadata`);
1233
1485
  }
1234
- const headers = new import_utils20.Headers({
1235
- "Content-Type": import_utils18.ContentType.XWwwFormUrlencoded
1486
+ const headers = new import_utils23.Headers({
1487
+ "Content-Type": import_utils21.ContentType.XWwwFormUrlencoded
1236
1488
  });
1237
1489
  await options.callbacks.clientAuthentication({
1238
1490
  url: introspectionEndpoint,
1239
1491
  method: "POST",
1240
- authorizationServerMetata: options.authorizationServerMetadata,
1492
+ authorizationServerMetadata: options.authorizationServerMetadata,
1241
1493
  body: introspectionRequest,
1242
- contentType: import_utils18.ContentType.XWwwFormUrlencoded,
1494
+ contentType: import_utils21.ContentType.XWwwFormUrlencoded,
1243
1495
  headers
1244
1496
  });
1245
1497
  const { result, response } = await fetchWithZod(
1246
1498
  zTokenIntrospectionResponse,
1247
- import_utils18.ContentType.Json,
1499
+ import_utils21.ContentType.Json,
1248
1500
  introspectionEndpoint,
1249
1501
  {
1250
- body: (0, import_utils18.objectToQueryParams)(introspectionRequest).toString(),
1502
+ body: (0, import_utils21.objectToQueryParams)(introspectionRequest).toString(),
1251
1503
  method: "POST",
1252
1504
  headers
1253
1505
  }
1254
1506
  );
1255
1507
  if (!response.ok || !result?.success) {
1256
- throw new import_utils19.InvalidFetchResponseError(
1508
+ throw new import_utils22.InvalidFetchResponseError(
1257
1509
  `Unable to introspect token from '${introspectionEndpoint}'. Received response with status ${response.status}`,
1258
1510
  await response.clone().text(),
1259
1511
  response
@@ -1297,7 +1549,7 @@ async function verifyResourceRequest(options) {
1297
1549
  resourceServer: options.resourceServer,
1298
1550
  now: options.now
1299
1551
  }).catch((error) => {
1300
- if (error instanceof Oauth2JwtParseError || error instanceof import_utils21.ValidationError) return null;
1552
+ if (error instanceof Oauth2JwtParseError || error instanceof import_utils24.ValidationError) return null;
1301
1553
  const errorMessage = error instanceof Oauth2Error ? error.message : "Invalid access token";
1302
1554
  throw new Oauth2ResourceUnauthorizedError(
1303
1555
  `Error occured during verification of jwt profile access token: ${error.message}`,
@@ -1389,7 +1641,7 @@ async function verifyResourceRequest(options) {
1389
1641
  }
1390
1642
  return {
1391
1643
  tokenPayload,
1392
- dpopJwk,
1644
+ dpop: dpopJwk ? { jwk: dpopJwk } : void 0,
1393
1645
  scheme,
1394
1646
  accessToken,
1395
1647
  authorizationServer: authorizationServer.issuer
@@ -1397,10 +1649,23 @@ async function verifyResourceRequest(options) {
1397
1649
  }
1398
1650
 
1399
1651
  // src/client-authentication.ts
1400
- var import_utils22 = require("@openid4vc/utils");
1652
+ var import_utils25 = require("@openid4vc/utils");
1653
+
1654
+ // src/z-grant-type.ts
1655
+ var import_zod13 = __toESM(require("zod"));
1656
+ var zPreAuthorizedCodeGrantIdentifier = import_zod13.default.literal("urn:ietf:params:oauth:grant-type:pre-authorized_code");
1657
+ var preAuthorizedCodeGrantIdentifier = zPreAuthorizedCodeGrantIdentifier.value;
1658
+ var zAuthorizationCodeGrantIdentifier = import_zod13.default.literal("authorization_code");
1659
+ var authorizationCodeGrantIdentifier = zAuthorizationCodeGrantIdentifier.value;
1660
+ var zRefreshTokenGrantIdentifier = import_zod13.default.literal("refresh_token");
1661
+ var refreshTokenGrantIdentifier = zRefreshTokenGrantIdentifier.value;
1662
+
1663
+ // src/client-authentication.ts
1401
1664
  var SupportedClientAuthenticationMethod = /* @__PURE__ */ ((SupportedClientAuthenticationMethod2) => {
1402
1665
  SupportedClientAuthenticationMethod2["ClientSecretBasic"] = "client_secret_basic";
1403
1666
  SupportedClientAuthenticationMethod2["ClientSecretPost"] = "client_secret_post";
1667
+ SupportedClientAuthenticationMethod2["ClientAttestationJwt"] = "attest_jwt_client_auth";
1668
+ SupportedClientAuthenticationMethod2["None"] = "none";
1404
1669
  return SupportedClientAuthenticationMethod2;
1405
1670
  })(SupportedClientAuthenticationMethod || {});
1406
1671
  function getSupportedClientAuthenticationMethod(authorizationServer, endpointType) {
@@ -1436,15 +1701,21 @@ function getSupportedClientAuthenticationMethod(authorizationServer, endpointTyp
1436
1701
  }
1437
1702
  function clientAuthenticationDynamic(options) {
1438
1703
  return (callbackOptions) => {
1439
- const { url, authorizationServerMetata } = callbackOptions;
1440
- const endpointType = url === authorizationServerMetata.introspection_endpoint ? "introspection" : "endpoint";
1441
- const method = getSupportedClientAuthenticationMethod(authorizationServerMetata, endpointType);
1704
+ const { url, authorizationServerMetadata, body } = callbackOptions;
1705
+ const endpointType = url === authorizationServerMetadata.introspection_endpoint ? "introspection" : url === authorizationServerMetadata.token_endpoint ? "token" : "endpoint";
1706
+ const method = getSupportedClientAuthenticationMethod(authorizationServerMetadata, endpointType);
1707
+ if (endpointType === "token" && body.grant_type === preAuthorizedCodeGrantIdentifier && authorizationServerMetadata.pre_authorized_grant_anonymous_access_supported) {
1708
+ return clientAuthenticationAnonymous()(callbackOptions);
1709
+ }
1442
1710
  if (method === "client_secret_basic" /* ClientSecretBasic */) {
1443
1711
  return clientAuthenticationClientSecretBasic(options)(callbackOptions);
1444
1712
  }
1445
1713
  if (method === "client_secret_post" /* ClientSecretPost */) {
1446
1714
  return clientAuthenticationClientSecretPost(options)(callbackOptions);
1447
1715
  }
1716
+ if (method === "none" /* None */) {
1717
+ return clientAuthenticationNone(options)(callbackOptions);
1718
+ }
1448
1719
  throw new Oauth2Error(
1449
1720
  `Unsupported client auth method ${method}. Supported values are ${Object.values(
1450
1721
  SupportedClientAuthenticationMethod
@@ -1460,40 +1731,61 @@ function clientAuthenticationClientSecretPost(options) {
1460
1731
  }
1461
1732
  function clientAuthenticationClientSecretBasic(options) {
1462
1733
  return ({ headers }) => {
1463
- const authorization = (0, import_utils22.encodeToBase64Url)((0, import_utils22.decodeUtf8String)(`${options.clientId}:${options.clientSecret}`));
1734
+ const authorization = (0, import_utils25.encodeToBase64Url)((0, import_utils25.decodeUtf8String)(`${options.clientId}:${options.clientSecret}`));
1464
1735
  headers.set("Authorization", `Basic ${authorization}`);
1465
1736
  };
1466
1737
  }
1467
- function clientAuthenticationNone() {
1738
+ function clientAuthenticationNone(options) {
1739
+ return ({ body }) => {
1740
+ body.client_id = options.clientId;
1741
+ };
1742
+ }
1743
+ function clientAuthenticationAnonymous() {
1468
1744
  return () => {
1469
1745
  };
1470
1746
  }
1747
+ function clientAuthenticationClientAttestationJwt(options) {
1748
+ return async ({ headers, authorizationServerMetadata }) => {
1749
+ const clientAttestationPop = await createClientAttestationPopJwt({
1750
+ authorizationServer: authorizationServerMetadata.issuer,
1751
+ callbacks: options.callbacks,
1752
+ clientAttestation: options.clientAttestationJwt
1753
+ // TODO: support client attestation nonce
1754
+ // We can fetch it before making the request if we don't have a nonce
1755
+ // https://www.ietf.org/archive/id/draft-ietf-oauth-attestation-based-client-auth-05.html
1756
+ // https://github.com/oauth-wg/draft-ietf-oauth-attestation-based-client-auth/issues/101
1757
+ // nonce:
1758
+ });
1759
+ headers.set(oauthClientAttestationHeader, options.clientAttestationJwt);
1760
+ headers.set(oauthClientAttestationPopHeader, clientAttestationPop);
1761
+ };
1762
+ }
1471
1763
 
1472
1764
  // src/Oauth2AuthorizationServer.ts
1473
- var import_utils34 = require("@openid4vc/utils");
1765
+ var import_utils37 = require("@openid4vc/utils");
1474
1766
 
1475
1767
  // src/access-token/create-access-token.ts
1476
- var import_utils23 = require("@openid4vc/utils");
1768
+ var import_utils26 = require("@openid4vc/utils");
1477
1769
  async function createAccessTokenJwt(options) {
1478
- const header = (0, import_utils23.parseWithErrorHandling)(zAccessTokenProfileJwtHeader, {
1770
+ const header = (0, import_utils26.parseWithErrorHandling)(zAccessTokenProfileJwtHeader, {
1479
1771
  ...jwtHeaderFromJwtSigner(options.signer),
1480
1772
  typ: "at+jwt"
1481
1773
  });
1482
1774
  const now = options.now ?? /* @__PURE__ */ new Date();
1483
- const payload = (0, import_utils23.parseWithErrorHandling)(zAccessTokenProfileJwtPayload, {
1484
- iat: (0, import_utils23.dateToSeconds)(now),
1485
- exp: (0, import_utils23.dateToSeconds)((0, import_utils23.addSecondsToDate)(now, options.expiresInSeconds)),
1775
+ const payload = (0, import_utils26.parseWithErrorHandling)(zAccessTokenProfileJwtPayload, {
1776
+ iat: (0, import_utils26.dateToSeconds)(now),
1777
+ exp: (0, import_utils26.dateToSeconds)((0, import_utils26.addSecondsToDate)(now, options.expiresInSeconds)),
1486
1778
  aud: options.audience,
1487
1779
  iss: options.authorizationServer,
1488
- jti: (0, import_utils23.encodeToBase64Url)(await options.callbacks.generateRandom(32)),
1780
+ jti: (0, import_utils26.encodeToBase64Url)(await options.callbacks.generateRandom(32)),
1489
1781
  client_id: options.clientId,
1490
1782
  sub: options.subject,
1491
1783
  scope: options.scope,
1492
- cnf: options.dpopJwk ? {
1784
+ cnf: options.dpop ? {
1493
1785
  jkt: await calculateJwkThumbprint({
1494
1786
  hashAlgorithm: "sha-256" /* Sha256 */,
1495
1787
  hashCallback: options.callbacks.hash,
1496
- jwk: options.dpopJwk
1788
+ jwk: options.dpop.jwk
1497
1789
  })
1498
1790
  } : void 0,
1499
1791
  ...options.additionalPayload
@@ -1508,45 +1800,34 @@ async function createAccessTokenJwt(options) {
1508
1800
  }
1509
1801
 
1510
1802
  // src/access-token/create-access-token-response.ts
1511
- var import_utils25 = require("@openid4vc/utils");
1512
-
1513
- // src/access-token/z-access-token.ts
1514
- var import_zod13 = __toESM(require("zod"));
1515
- var import_utils24 = require("@openid4vc/utils");
1516
-
1517
- // src/z-grant-type.ts
1518
- var import_zod12 = __toESM(require("zod"));
1519
- var zPreAuthorizedCodeGrantIdentifier = import_zod12.default.literal("urn:ietf:params:oauth:grant-type:pre-authorized_code");
1520
- var preAuthorizedCodeGrantIdentifier = zPreAuthorizedCodeGrantIdentifier.value;
1521
- var zAuthorizationCodeGrantIdentifier = import_zod12.default.literal("authorization_code");
1522
- var authorizationCodeGrantIdentifier = zAuthorizationCodeGrantIdentifier.value;
1523
- var zRefreshTokenGrantIdentifier = import_zod12.default.literal("refresh_token");
1524
- var refreshTokenGrantIdentifier = zRefreshTokenGrantIdentifier.value;
1803
+ var import_utils28 = require("@openid4vc/utils");
1525
1804
 
1526
1805
  // src/access-token/z-access-token.ts
1527
- var zAccessTokenRequest = import_zod13.default.intersection(
1528
- import_zod13.default.object({
1806
+ var import_zod14 = __toESM(require("zod"));
1807
+ var import_utils27 = require("@openid4vc/utils");
1808
+ var zAccessTokenRequest = import_zod14.default.intersection(
1809
+ import_zod14.default.object({
1529
1810
  // Pre authorized code flow
1530
- "pre-authorized_code": import_zod13.default.optional(import_zod13.default.string()),
1811
+ "pre-authorized_code": import_zod14.default.optional(import_zod14.default.string()),
1531
1812
  // Authorization code flow
1532
- code: import_zod13.default.optional(import_zod13.default.string()),
1533
- redirect_uri: import_zod13.default.string().url().optional(),
1813
+ code: import_zod14.default.optional(import_zod14.default.string()),
1814
+ redirect_uri: import_zod14.default.string().url().optional(),
1534
1815
  // Refresh token grant
1535
- refresh_token: import_zod13.default.optional(import_zod13.default.string()),
1536
- resource: import_zod13.default.optional(import_utils24.zHttpsUrl),
1537
- code_verifier: import_zod13.default.optional(import_zod13.default.string()),
1538
- grant_type: import_zod13.default.union([
1816
+ refresh_token: import_zod14.default.optional(import_zod14.default.string()),
1817
+ resource: import_zod14.default.optional(import_utils27.zHttpsUrl),
1818
+ code_verifier: import_zod14.default.optional(import_zod14.default.string()),
1819
+ grant_type: import_zod14.default.union([
1539
1820
  zPreAuthorizedCodeGrantIdentifier,
1540
1821
  zAuthorizationCodeGrantIdentifier,
1541
1822
  zRefreshTokenGrantIdentifier,
1542
1823
  // string makes the previous ones unessary, but it does help with error messages
1543
- import_zod13.default.string()
1824
+ import_zod14.default.string()
1544
1825
  ])
1545
1826
  }).passthrough(),
1546
- import_zod13.default.object({
1547
- tx_code: import_zod13.default.optional(import_zod13.default.string()),
1827
+ import_zod14.default.object({
1828
+ tx_code: import_zod14.default.optional(import_zod14.default.string()),
1548
1829
  // user_pin is from OpenID4VCI draft 11
1549
- user_pin: import_zod13.default.optional(import_zod13.default.string())
1830
+ user_pin: import_zod14.default.optional(import_zod14.default.string())
1550
1831
  }).passthrough().refine(({ tx_code, user_pin }) => !tx_code || !user_pin || user_pin === tx_code, {
1551
1832
  message: `If both 'tx_code' and 'user_pin' are present they must match`
1552
1833
  }).transform(({ tx_code, user_pin, ...rest }) => {
@@ -1556,20 +1837,20 @@ var zAccessTokenRequest = import_zod13.default.intersection(
1556
1837
  };
1557
1838
  })
1558
1839
  );
1559
- var zAccessTokenResponse = import_zod13.default.object({
1560
- access_token: import_zod13.default.string(),
1561
- token_type: import_zod13.default.string(),
1562
- expires_in: import_zod13.default.optional(import_zod13.default.number().int()),
1563
- scope: import_zod13.default.optional(import_zod13.default.string()),
1564
- state: import_zod13.default.optional(import_zod13.default.string()),
1565
- refresh_token: import_zod13.default.optional(import_zod13.default.string()),
1840
+ var zAccessTokenResponse = import_zod14.default.object({
1841
+ access_token: import_zod14.default.string(),
1842
+ token_type: import_zod14.default.string(),
1843
+ expires_in: import_zod14.default.optional(import_zod14.default.number().int()),
1844
+ scope: import_zod14.default.optional(import_zod14.default.string()),
1845
+ state: import_zod14.default.optional(import_zod14.default.string()),
1846
+ refresh_token: import_zod14.default.optional(import_zod14.default.string()),
1566
1847
  // OpenID4VCI specific parameters
1567
- c_nonce: import_zod13.default.optional(import_zod13.default.string()),
1568
- c_nonce_expires_in: import_zod13.default.optional(import_zod13.default.number().int()),
1848
+ c_nonce: import_zod14.default.optional(import_zod14.default.string()),
1849
+ c_nonce_expires_in: import_zod14.default.optional(import_zod14.default.number().int()),
1569
1850
  // TODO: add additional params
1570
- authorization_details: import_zod13.default.array(
1571
- import_zod13.default.object({
1572
- // requried when type is openid_credential (so we probably need a discriminator)
1851
+ authorization_details: import_zod14.default.array(
1852
+ import_zod14.default.object({
1853
+ // required when type is openid_credential (so we probably need a discriminator)
1573
1854
  // credential_identifiers: z.array(z.string()),
1574
1855
  }).passthrough()
1575
1856
  ).optional()
@@ -1578,7 +1859,7 @@ var zAccessTokenErrorResponse = zOauth2ErrorResponse;
1578
1859
 
1579
1860
  // src/access-token/create-access-token-response.ts
1580
1861
  async function createAccessTokenResponse(options) {
1581
- const accessTokenResponse = (0, import_utils25.parseWithErrorHandling)(zAccessTokenResponse, {
1862
+ const accessTokenResponse = (0, import_utils28.parseWithErrorHandling)(zAccessTokenResponse, {
1582
1863
  access_token: options.accessToken,
1583
1864
  token_type: options.tokenType,
1584
1865
  expires_in: options.expiresInSeconds,
@@ -1590,13 +1871,14 @@ async function createAccessTokenResponse(options) {
1590
1871
  }
1591
1872
 
1592
1873
  // src/access-token/parse-access-token-request.ts
1874
+ var import_utils29 = require("@openid4vc/utils");
1593
1875
  function parseAccessTokenRequest(options) {
1594
1876
  const parsedAccessTokenRequest = zAccessTokenRequest.safeParse(options.accessTokenRequest);
1595
1877
  if (!parsedAccessTokenRequest.success) {
1596
1878
  throw new Oauth2ServerErrorResponseError({
1597
1879
  error: "invalid_request" /* InvalidRequest */,
1598
1880
  error_description: `Error occured during validation of authorization request.
1599
- ${JSON.stringify(parsedAccessTokenRequest.error.issues, null, 2)}`
1881
+ ${(0, import_utils29.formatZodError)(parsedAccessTokenRequest.error)}`
1600
1882
  });
1601
1883
  }
1602
1884
  const accessTokenRequest = parsedAccessTokenRequest.data;
@@ -1637,17 +1919,30 @@ ${JSON.stringify(parsedAccessTokenRequest.error.issues, null, 2)}`
1637
1919
  error_description: `Request contains a 'DPoP' header, but the value is not a valid DPoP jwt`
1638
1920
  });
1639
1921
  }
1922
+ const extractedClientAttestationJwts = extractClientAttestationJwtsFromHeaders(options.request.headers);
1923
+ if (!extractedClientAttestationJwts.valid) {
1924
+ throw new Oauth2ServerErrorResponseError({
1925
+ error: "invalid_client" /* InvalidClient */,
1926
+ error_description: "Request contains client attestation header, but the values are not valid client attestation and client attestation PoP header."
1927
+ });
1928
+ }
1640
1929
  const pkceCodeVerifier = accessTokenRequest.code_verifier;
1641
1930
  return {
1642
1931
  accessTokenRequest,
1643
1932
  grant,
1644
- dpopJwt: extractedDpopJwt.dpopJwt,
1933
+ dpop: extractedDpopJwt.dpopJwt ? {
1934
+ jwt: extractedDpopJwt.dpopJwt
1935
+ } : void 0,
1936
+ clientAttestation: extractedClientAttestationJwts.clientAttestationHeader ? {
1937
+ clientAttestationJwt: extractedClientAttestationJwts.clientAttestationHeader,
1938
+ clientAttestationPopJwt: extractedClientAttestationJwts.clientAttestationPopHeader
1939
+ } : void 0,
1645
1940
  pkceCodeVerifier
1646
1941
  };
1647
1942
  }
1648
1943
 
1649
1944
  // src/pkce.ts
1650
- var import_utils26 = require("@openid4vc/utils");
1945
+ var import_utils30 = require("@openid4vc/utils");
1651
1946
  var PkceCodeChallengeMethod = /* @__PURE__ */ ((PkceCodeChallengeMethod2) => {
1652
1947
  PkceCodeChallengeMethod2["Plain"] = "plain";
1653
1948
  PkceCodeChallengeMethod2["S256"] = "S256";
@@ -1662,7 +1957,7 @@ async function createPkce(options) {
1662
1957
  throw new Oauth2Error(`Unable to create PKCE code verifier. 'allowedCodeChallengeMethods' is an empty array.`);
1663
1958
  }
1664
1959
  const codeChallengeMethod = allowedCodeChallengeMethods.includes("S256" /* S256 */) ? "S256" /* S256 */ : "plain" /* Plain */;
1665
- const codeVerifier = options.codeVerifier ?? (0, import_utils26.encodeToBase64Url)(await options.callbacks.generateRandom(64));
1960
+ const codeVerifier = options.codeVerifier ?? (0, import_utils30.encodeToBase64Url)(await options.callbacks.generateRandom(64));
1666
1961
  return {
1667
1962
  codeVerifier,
1668
1963
  codeChallenge: await calculateCodeChallenge({
@@ -1690,13 +1985,24 @@ async function calculateCodeChallenge(options) {
1690
1985
  return options.codeVerifier;
1691
1986
  }
1692
1987
  if (options.codeChallengeMethod === "S256" /* S256 */) {
1693
- return (0, import_utils26.encodeToBase64Url)(await options.hashCallback((0, import_utils26.decodeUtf8String)(options.codeVerifier), "sha-256" /* Sha256 */));
1988
+ return (0, import_utils30.encodeToBase64Url)(await options.hashCallback((0, import_utils30.decodeUtf8String)(options.codeVerifier), "sha-256" /* Sha256 */));
1694
1989
  }
1695
1990
  throw new Oauth2Error(`Unsupported code challenge method ${options.codeChallengeMethod}`);
1696
1991
  }
1697
1992
 
1698
1993
  // src/access-token/verify-access-token-request.ts
1699
1994
  async function verifyPreAuthorizedCodeAccessTokenRequest(options) {
1995
+ if (options.pkce) {
1996
+ await verifyAccessTokenRequestPkce(options.pkce, options.callbacks);
1997
+ }
1998
+ const dpopResult = options.dpop ? await verifyAccessTokenRequestDpop(options.dpop, options.request, options.callbacks) : void 0;
1999
+ const clientAttestationResult = options.clientAttestation ? await verifyAccessTokenRequestClientAttestation(
2000
+ options.clientAttestation,
2001
+ options.authorizationServerMetadata,
2002
+ options.callbacks,
2003
+ dpopResult?.jwkThumbprint,
2004
+ options.now
2005
+ ) : void 0;
1700
2006
  if (options.grant.preAuthorizedCode !== options.expectedPreAuthorizedCode) {
1701
2007
  throw new Oauth2ServerErrorResponseError({
1702
2008
  error: "invalid_grant" /* InvalidGrant */,
@@ -1735,13 +2041,20 @@ async function verifyPreAuthorizedCodeAccessTokenRequest(options) {
1735
2041
  );
1736
2042
  }
1737
2043
  }
2044
+ return { dpop: dpopResult, clientAttestation: clientAttestationResult };
2045
+ }
2046
+ async function verifyAuthorizationCodeAccessTokenRequest(options) {
1738
2047
  if (options.pkce) {
1739
2048
  await verifyAccessTokenRequestPkce(options.pkce, options.callbacks);
1740
2049
  }
1741
- const dpopResult = options.dpop ? await verifyAccessTokenRequestDpop(options.dpop, options.request, options.callbacks) : null;
1742
- return { dpopJwk: dpopResult?.dpopJwk };
1743
- }
1744
- async function verifyAuthorizationCodeAccessTokenRequest(options) {
2050
+ const dpopResult = options.dpop ? await verifyAccessTokenRequestDpop(options.dpop, options.request, options.callbacks) : void 0;
2051
+ const clientAttestationResult = options.clientAttestation ? await verifyAccessTokenRequestClientAttestation(
2052
+ options.clientAttestation,
2053
+ options.authorizationServerMetadata,
2054
+ options.callbacks,
2055
+ dpopResult?.jwkThumbprint,
2056
+ options.now
2057
+ ) : void 0;
1745
2058
  if (options.grant.code !== options.expectedCode) {
1746
2059
  throw new Oauth2ServerErrorResponseError({
1747
2060
  error: "invalid_grant" /* InvalidGrant */,
@@ -1762,11 +2075,55 @@ async function verifyAuthorizationCodeAccessTokenRequest(options) {
1762
2075
  );
1763
2076
  }
1764
2077
  }
1765
- if (options.pkce) {
1766
- await verifyAccessTokenRequestPkce(options.pkce, options.callbacks);
2078
+ return { dpop: dpopResult, clientAttestation: clientAttestationResult };
2079
+ }
2080
+ async function verifyAccessTokenRequestClientAttestation(options, authorizationServerMetadata, callbacks, dpopJwkThumbprint, now) {
2081
+ if (!options.clientAttestationJwt || !options.clientAttestationPopJwt) {
2082
+ if (!options.required && !options.clientAttestationJwt && !options.clientAttestationPopJwt) {
2083
+ return void 0;
2084
+ }
2085
+ throw new Oauth2ServerErrorResponseError({
2086
+ error: "invalid_dpop_proof" /* InvalidDpopProof */,
2087
+ error_description: `Missing required client attestation parameters in access token request. Make sure to provide the '${oauthClientAttestationHeader}' and '${oauthClientAttestationPopHeader}' header values.`
2088
+ });
2089
+ }
2090
+ const verifiedClientAttestation = await verifyClientAttestation({
2091
+ authorizationServer: authorizationServerMetadata.issuer,
2092
+ callbacks,
2093
+ clientAttestationJwt: options.clientAttestationJwt,
2094
+ clientAttestationPopJwt: options.clientAttestationPopJwt,
2095
+ now
2096
+ });
2097
+ if (options.expectedClientId !== verifiedClientAttestation.clientAttestation.payload.sub) {
2098
+ throw new Oauth2ServerErrorResponseError(
2099
+ {
2100
+ error: "invalid_client" /* InvalidClient */,
2101
+ error_description: `The client id '${verifiedClientAttestation.clientAttestation.payload.sub}' in the client attestation does not match the client id for the authorization.`
2102
+ },
2103
+ {
2104
+ status: 401
2105
+ }
2106
+ );
2107
+ }
2108
+ if (options.ensureConfirmationKeyMatchesDpopKey && dpopJwkThumbprint) {
2109
+ const clientAttestationJkt = await calculateJwkThumbprint({
2110
+ hashAlgorithm: "sha-256" /* Sha256 */,
2111
+ hashCallback: callbacks.hash,
2112
+ jwk: verifiedClientAttestation.clientAttestation.payload.cnf.jwk
2113
+ });
2114
+ if (clientAttestationJkt !== dpopJwkThumbprint) {
2115
+ throw new Oauth2ServerErrorResponseError(
2116
+ {
2117
+ error: "invalid_request" /* InvalidRequest */,
2118
+ error_description: "Expected the DPoP JWK thumbprint value to match the JWK thumbprint of the client attestation confirmation JWK. Ensrue both DPoP and client attestation use the same key."
2119
+ },
2120
+ {
2121
+ status: 401
2122
+ }
2123
+ );
2124
+ }
1767
2125
  }
1768
- const dpopResult = options.dpop ? await verifyAccessTokenRequestDpop(options.dpop, options.request, options.callbacks) : null;
1769
- return { dpopJwk: dpopResult?.dpopJwk };
2126
+ return verifiedClientAttestation;
1770
2127
  }
1771
2128
  async function verifyAccessTokenRequestDpop(options, request, callbacks) {
1772
2129
  if (options.required && !options.jwt) {
@@ -1775,26 +2132,18 @@ async function verifyAccessTokenRequestDpop(options, request, callbacks) {
1775
2132
  error_description: "Missing required DPoP proof"
1776
2133
  });
1777
2134
  }
1778
- if (!options.jwt) return null;
1779
- try {
1780
- const { header } = await verifyDpopJwt({
1781
- callbacks,
1782
- dpopJwt: options.jwt,
1783
- request,
1784
- allowedSigningAlgs: options.allowedSigningAlgs
1785
- });
1786
- return {
1787
- dpopJwk: header.jwk
1788
- };
1789
- } catch (error) {
1790
- if (error instanceof Oauth2Error) {
1791
- throw new Oauth2ServerErrorResponseError({
1792
- error: "invalid_dpop_proof" /* InvalidDpopProof */,
1793
- error_description: error.message
1794
- });
1795
- }
1796
- throw error;
1797
- }
2135
+ if (!options.jwt) return void 0;
2136
+ const { header, jwkThumbprint } = await verifyDpopJwt({
2137
+ callbacks,
2138
+ dpopJwt: options.jwt,
2139
+ request,
2140
+ allowedSigningAlgs: options.allowedSigningAlgs,
2141
+ expectedJwkThumbprint: options.expectedJwkThumbprint
2142
+ });
2143
+ return {
2144
+ jwk: header.jwk,
2145
+ jwkThumbprint
2146
+ };
1798
2147
  }
1799
2148
  async function verifyAccessTokenRequestPkce(options, callbacks) {
1800
2149
  if (options.codeChallenge && !options.codeVerifier) {
@@ -1823,281 +2172,298 @@ async function verifyAccessTokenRequestPkce(options, callbacks) {
1823
2172
  }
1824
2173
 
1825
2174
  // src/authorization-challenge/create-authorization-challenge-response.ts
1826
- var import_utils29 = require("@openid4vc/utils");
2175
+ var import_utils33 = require("@openid4vc/utils");
1827
2176
 
1828
2177
  // src/authorization-challenge/z-authorization-challenge.ts
1829
- var import_utils28 = require("@openid4vc/utils");
1830
- var import_zod15 = __toESM(require("zod"));
2178
+ var import_utils32 = require("@openid4vc/utils");
2179
+ var import_zod16 = __toESM(require("zod"));
1831
2180
 
1832
2181
  // src/authorization-request/z-authorization-request.ts
1833
- var import_utils27 = require("@openid4vc/utils");
1834
- var import_zod14 = __toESM(require("zod"));
1835
- var zAuthorizationRequest = import_zod14.default.object({
1836
- response_type: import_zod14.default.string(),
1837
- client_id: import_zod14.default.string(),
1838
- issuer_state: import_zod14.default.optional(import_zod14.default.string()),
1839
- redirect_uri: import_zod14.default.string().url().optional(),
1840
- resource: import_zod14.default.optional(import_utils27.zHttpsUrl),
1841
- scope: import_zod14.default.optional(import_zod14.default.string()),
2182
+ var import_utils31 = require("@openid4vc/utils");
2183
+ var import_zod15 = __toESM(require("zod"));
2184
+ var zAuthorizationRequest = import_zod15.default.object({
2185
+ response_type: import_zod15.default.string(),
2186
+ client_id: import_zod15.default.string(),
2187
+ issuer_state: import_zod15.default.optional(import_zod15.default.string()),
2188
+ redirect_uri: import_zod15.default.string().url().optional(),
2189
+ resource: import_zod15.default.optional(import_utils31.zHttpsUrl),
2190
+ scope: import_zod15.default.optional(import_zod15.default.string()),
1842
2191
  // DPoP jwk thumbprint
1843
- dpop_jkt: import_zod14.default.optional(import_zod14.default.string()),
1844
- code_challenge: import_zod14.default.optional(import_zod14.default.string()),
1845
- code_challenge_method: import_zod14.default.optional(import_zod14.default.string())
2192
+ dpop_jkt: import_zod15.default.optional(import_zod15.default.string().base64url()),
2193
+ code_challenge: import_zod15.default.optional(import_zod15.default.string()),
2194
+ code_challenge_method: import_zod15.default.optional(import_zod15.default.string())
1846
2195
  }).passthrough();
1847
- var zPushedAuthorizationRequest = import_zod14.default.object({
1848
- request_uri: import_zod14.default.string(),
1849
- client_id: import_zod14.default.string()
2196
+ var zPushedAuthorizationRequest = import_zod15.default.object({
2197
+ request_uri: import_zod15.default.string(),
2198
+ client_id: import_zod15.default.string()
1850
2199
  }).passthrough();
1851
- var zPushedAuthorizationResponse = import_zod14.default.object({
1852
- request_uri: import_zod14.default.string(),
1853
- expires_in: import_zod14.default.number().int()
2200
+ var zPushedAuthorizationResponse = import_zod15.default.object({
2201
+ request_uri: import_zod15.default.string(),
2202
+ expires_in: import_zod15.default.number().int()
1854
2203
  }).passthrough();
1855
2204
 
1856
2205
  // src/authorization-challenge/z-authorization-challenge.ts
1857
- var zAuthorizationChallengeRequest = import_zod15.default.object({
2206
+ var zAuthorizationChallengeRequest = import_zod16.default.object({
1858
2207
  // authorization challenge request can include same parameters as an authorization request
1859
2208
  // except for response_type (always `code`), and `client_id` is optional (becase
1860
2209
  // it's possible to do client authentication using different methods)
1861
2210
  ...zAuthorizationRequest.omit({ response_type: true, client_id: true }).shape,
1862
- client_id: import_zod15.default.optional(zAuthorizationRequest.shape.client_id),
1863
- auth_session: import_zod15.default.optional(import_zod15.default.string()),
2211
+ client_id: import_zod16.default.optional(zAuthorizationRequest.shape.client_id),
2212
+ auth_session: import_zod16.default.optional(import_zod16.default.string()),
1864
2213
  // DRAFT presentation during issuance
1865
- presentation_during_issuance_session: import_zod15.default.optional(import_zod15.default.string())
2214
+ presentation_during_issuance_session: import_zod16.default.optional(import_zod16.default.string())
1866
2215
  }).passthrough();
1867
- var zAuthorizationChallengeResponse = import_zod15.default.object({
1868
- authorization_code: import_zod15.default.string()
2216
+ var zAuthorizationChallengeResponse = import_zod16.default.object({
2217
+ authorization_code: import_zod16.default.string()
1869
2218
  }).passthrough();
1870
- var zAuthorizationChallengeErrorResponse = import_zod15.default.object({
2219
+ var zAuthorizationChallengeErrorResponse = import_zod16.default.object({
1871
2220
  ...zOauth2ErrorResponse.shape,
1872
- auth_session: import_zod15.default.optional(import_zod15.default.string()),
1873
- request_uri: import_zod15.default.optional(import_zod15.default.string()),
1874
- expires_in: import_zod15.default.optional(import_utils28.zInteger),
2221
+ auth_session: import_zod16.default.optional(import_zod16.default.string()),
2222
+ request_uri: import_zod16.default.optional(import_zod16.default.string()),
2223
+ expires_in: import_zod16.default.optional(import_utils32.zInteger),
1875
2224
  // DRAFT: presentation during issuance
1876
- presentation: import_zod15.default.optional(import_zod15.default.string())
2225
+ presentation: import_zod16.default.optional(import_zod16.default.string())
1877
2226
  }).passthrough();
1878
2227
 
1879
2228
  // src/authorization-challenge/create-authorization-challenge-response.ts
1880
2229
  function createAuthorizationChallengeResponse(options) {
1881
- const authorizationChallengeResponse = (0, import_utils29.parseWithErrorHandling)(zAuthorizationChallengeResponse, {
1882
- ...options.additionalPayload,
1883
- authorization_code: options.authorizationCode
1884
- });
1885
- return { authorizationChallengeResponse };
1886
- }
1887
- function createAuthorizationChallengeErrorResponse(options) {
1888
- const authorizationChallengeErrorResponse = (0, import_utils29.parseWithErrorHandling)(zAuthorizationChallengeErrorResponse, {
2230
+ const authorizationChallengeResponse = (0, import_utils33.parseWithErrorHandling)(zAuthorizationChallengeResponse, {
1889
2231
  ...options.additionalPayload,
1890
- // General FiPA
1891
- error: options.error,
1892
- error_description: options.errorDescription,
1893
- auth_session: options.authSession,
1894
- // Presentation during issuance
1895
- presentation: options.presentation,
1896
- // PAR
1897
- request_uri: options.requestUri,
1898
- expires_in: options.expiresIn
1899
- });
1900
- return authorizationChallengeErrorResponse;
1901
- }
1902
-
1903
- // src/authorization-challenge/parse-authorization-challenge-request.ts
1904
- var import_utils30 = require("@openid4vc/utils");
1905
- function parseAuthorizationChallengeRequest(options) {
1906
- const authorizationChallengeRequest = (0, import_utils30.parseWithErrorHandling)(
1907
- zAuthorizationChallengeRequest,
1908
- options.authorizationChallengeRequest
1909
- );
1910
- return { authorizationChallengeRequest };
1911
- }
1912
-
1913
- // src/client-attestation/clent-attestation.ts
1914
- var import_utils32 = require("@openid4vc/utils");
1915
-
1916
- // src/client-attestation/z-client-attestation.ts
1917
- var import_utils31 = require("@openid4vc/utils");
1918
- var import_zod16 = __toESM(require("zod"));
1919
- var zOauthClientAttestationHeader = import_zod16.default.literal("OAuth-Client-Attestation");
1920
- var oauthClientAttestationHeader = zOauthClientAttestationHeader.value;
1921
- var zClientAttestationJwtPayload = import_zod16.default.object({
1922
- ...zJwtPayload.shape,
1923
- iss: import_zod16.default.string(),
1924
- sub: import_zod16.default.string(),
1925
- exp: import_utils31.zInteger,
1926
- cnf: import_zod16.default.object({
1927
- jwk: zJwk,
1928
- key_type: import_zod16.default.optional(
1929
- import_zod16.default.union([
1930
- import_zod16.default.enum(["software", "hardware", "tee", "secure_enclave", "strong_box", "secure_element", "hsm"]),
1931
- import_zod16.default.string()
1932
- ])
1933
- ),
1934
- user_authentication: import_zod16.default.optional(
1935
- import_zod16.default.union([
1936
- import_zod16.default.enum(["system_biometry", "system_pin", "internal_biometry", "internal_pin", "secure_element_pin"]),
1937
- import_zod16.default.string()
1938
- ])
1939
- )
1940
- }).passthrough(),
1941
- aal: import_zod16.default.optional(import_zod16.default.string())
1942
- }).passthrough();
1943
- var zClientAttestationJwtHeader = import_zod16.default.object({
1944
- ...zJwtHeader.shape,
1945
- typ: import_zod16.default.literal("oauth-client-attestation+jwt")
1946
- }).passthrough();
1947
- var zOauthClientAttestationPopHeader = import_zod16.default.literal("OAuth-Client-Attestation-PoP");
1948
- var oauthClientAttestationPopHeader = zOauthClientAttestationPopHeader.value;
1949
- var zClientAttestationPopJwtPayload = import_zod16.default.object({
1950
- ...zJwtPayload.shape,
1951
- iss: import_zod16.default.string(),
1952
- exp: import_utils31.zInteger,
1953
- aud: import_utils31.zHttpsUrl,
1954
- jti: import_zod16.default.string(),
1955
- nonce: import_zod16.default.optional(import_zod16.default.string())
1956
- }).passthrough();
1957
- var zClientAttestationPopJwtHeader = import_zod16.default.object({
1958
- ...zJwtHeader.shape,
1959
- typ: import_zod16.default.literal("oauth-client-attestation-pop+jwt")
1960
- }).passthrough();
1961
-
1962
- // src/client-attestation/clent-attestation.ts
1963
- async function verifyClientAttestationJwt(options) {
1964
- const { header, payload } = decodeJwt({
1965
- jwt: options.clientAttestationJwt,
1966
- headerSchema: zClientAttestationJwtHeader,
1967
- payloadSchema: zClientAttestationJwtPayload
1968
- });
1969
- const { signer } = await verifyJwt({
1970
- signer: jwtSignerFromJwt({ header, payload }),
1971
- now: options.now,
1972
- header,
1973
- payload,
1974
- compact: options.clientAttestationJwt,
1975
- verifyJwtCallback: options.callbacks.verifyJwt,
1976
- errorMessage: "client attestation jwt verification failed"
1977
- });
1978
- return {
1979
- header,
1980
- payload,
1981
- signer
1982
- };
1983
- }
1984
- async function createClientAttestationJwt(options) {
1985
- const header = (0, import_utils32.parseWithErrorHandling)(zClientAttestationJwtHeader, {
1986
- typ: "oauth-client-attestation+jwt",
1987
- ...jwtHeaderFromJwtSigner(options.signer)
1988
- });
1989
- const payload = (0, import_utils32.parseWithErrorHandling)(zClientAttestationJwtPayload, {
1990
- iss: options.issuer,
1991
- iat: (0, import_utils32.dateToSeconds)(options.issuedAt),
1992
- exp: (0, import_utils32.dateToSeconds)(options.expiresAt),
1993
- sub: options.clientId,
1994
- cnf: options.confirmation,
1995
- ...options.additionalPayload
2232
+ authorization_code: options.authorizationCode
1996
2233
  });
1997
- const { jwt } = await options.callbacks.signJwt(options.signer, {
1998
- header,
1999
- payload
2234
+ return { authorizationChallengeResponse };
2235
+ }
2236
+ function createAuthorizationChallengeErrorResponse(options) {
2237
+ const authorizationChallengeErrorResponse = (0, import_utils33.parseWithErrorHandling)(zAuthorizationChallengeErrorResponse, {
2238
+ ...options.additionalPayload,
2239
+ // General FiPA
2240
+ error: options.error,
2241
+ error_description: options.errorDescription,
2242
+ auth_session: options.authSession,
2243
+ // Presentation during issuance
2244
+ presentation: options.presentation,
2245
+ // PAR
2246
+ request_uri: options.requestUri,
2247
+ expires_in: options.expiresIn
2000
2248
  });
2001
- return jwt;
2249
+ return authorizationChallengeErrorResponse;
2002
2250
  }
2003
- function extractClientAttestationJwtsFromHeaders(headers) {
2004
- const clientAttestationHeader = headers.get(oauthClientAttestationHeader);
2005
- const clientAttestationPopHeader = headers.get(oauthClientAttestationPopHeader);
2006
- if (!clientAttestationHeader || clientAttestationHeader.includes(",")) {
2007
- throw new Oauth2Error(`Missing or invalid '${oauthClientAttestationHeader}' header.`);
2251
+
2252
+ // src/authorization-challenge/parse-authorization-challenge-request.ts
2253
+ var import_utils34 = require("@openid4vc/utils");
2254
+
2255
+ // src/authorization-request/parse-authorization-request.ts
2256
+ function parseAuthorizationRequest(options) {
2257
+ const extractedDpopJwt = extractDpopJwtFromHeaders(options.request.headers);
2258
+ if (!extractedDpopJwt.valid) {
2259
+ throw new Oauth2ServerErrorResponseError({
2260
+ error: "invalid_dpop_proof" /* InvalidDpopProof */,
2261
+ error_description: `Request contains a 'DPoP' header, but the value is not a valid DPoP jwt`
2262
+ });
2008
2263
  }
2009
- if (!clientAttestationPopHeader || clientAttestationPopHeader.includes(",")) {
2010
- throw new Oauth2Error(`Missing or invalid '${oauthClientAttestationPopHeader}' header.`);
2264
+ const extractedClientAttestationJwts = extractClientAttestationJwtsFromHeaders(options.request.headers);
2265
+ if (!extractedClientAttestationJwts.valid) {
2266
+ throw new Oauth2ServerErrorResponseError({
2267
+ error: "invalid_client" /* InvalidClient */,
2268
+ error_description: "Request contains client attestation header, but the values are not valid client attestation and client attestation PoP header."
2269
+ });
2011
2270
  }
2012
2271
  return {
2013
- clientAttestationPopHeader,
2014
- clientAttestationHeader
2272
+ dpop: extractedDpopJwt.dpopJwt ? {
2273
+ jwt: extractedDpopJwt.dpopJwt,
2274
+ jwkThumbprint: options.authorizationRequest.dpop_jkt
2275
+ } : (
2276
+ // Basically the same as above, but with correct TS type hinting
2277
+ options.authorizationRequest.dpop_jkt ? {
2278
+ jwt: extractedDpopJwt.dpopJwt,
2279
+ jwkThumbprint: options.authorizationRequest.dpop_jkt
2280
+ } : void 0
2281
+ ),
2282
+ clientAttestation: extractedClientAttestationJwts.clientAttestationHeader ? {
2283
+ clientAttestationJwt: extractedClientAttestationJwts.clientAttestationHeader,
2284
+ clientAttestationPopJwt: extractedClientAttestationJwts.clientAttestationPopHeader
2285
+ } : void 0
2015
2286
  };
2016
2287
  }
2017
2288
 
2018
- // src/client-attestation/client-attestation-pop.ts
2019
- var import_utils33 = require("@openid4vc/utils");
2020
- async function createClientAttestationForRequest(options) {
2021
- const clientAttestationPopJwt = await createClientAttestationPopJwt({
2022
- authorizationServer: options.authorizationServer,
2023
- clientAttestation: options.clientAttestation.jwt,
2024
- callbacks: options.callbacks,
2025
- expiresAt: options.clientAttestation.expiresAt,
2026
- signer: options.clientAttestation.signer,
2027
- nonce: options.clientAttestation.nonce
2289
+ // src/authorization-challenge/parse-authorization-challenge-request.ts
2290
+ function parseAuthorizationChallengeRequest(options) {
2291
+ const parsedAuthorizationChallengeRequest = zAuthorizationChallengeRequest.safeParse(
2292
+ options.authorizationChallengeRequest
2293
+ );
2294
+ if (!parsedAuthorizationChallengeRequest.success) {
2295
+ throw new Oauth2ServerErrorResponseError({
2296
+ error: "invalid_request" /* InvalidRequest */,
2297
+ error_description: `Error occured during validation of authorization challenge request.
2298
+ ${(0, import_utils34.formatZodError)(parsedAuthorizationChallengeRequest.error)}`
2299
+ });
2300
+ }
2301
+ const authorizationChallengeRequest = parsedAuthorizationChallengeRequest.data;
2302
+ const { clientAttestation, dpop } = parseAuthorizationRequest({
2303
+ authorizationRequest: authorizationChallengeRequest,
2304
+ request: options.request
2028
2305
  });
2029
2306
  return {
2030
- headers: {
2031
- [oauthClientAttestationHeader]: options.clientAttestation.jwt,
2032
- [oauthClientAttestationPopHeader]: clientAttestationPopJwt
2033
- },
2034
- body: options.clientAttestation.includeLegacyDraft2ClientAssertion ? {
2035
- client_assertion: `${options.clientAttestation.jwt}~${clientAttestationPopJwt}`,
2036
- client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-client-attestation"
2037
- } : void 0
2307
+ authorizationChallengeRequest: parsedAuthorizationChallengeRequest.data,
2308
+ dpop,
2309
+ clientAttestation
2038
2310
  };
2039
2311
  }
2040
- async function verifyClientAttestationPopJwt(options) {
2041
- const { header, payload } = decodeJwt({
2042
- jwt: options.clientAttestationPopJwt,
2043
- headerSchema: zClientAttestationPopJwtHeader,
2044
- payloadSchema: zClientAttestationPopJwtPayload
2312
+
2313
+ // src/authorization-request/verify-authorization-request.ts
2314
+ async function verifyAuthorizationRequest(options) {
2315
+ const dpopResult = options.dpop ? await verifyAuthorizationRequestDpop(options.dpop, options.request, options.callbacks, options.now) : void 0;
2316
+ const clientAttestationResult = options.clientAttestation ? await verifyAuthorizationRequestClientAttestation(
2317
+ options.clientAttestation,
2318
+ options.authorizationServerMetadata,
2319
+ options.callbacks,
2320
+ dpopResult?.jwkThumbprint,
2321
+ options.now,
2322
+ options.authorizationRequest.client_id
2323
+ ) : void 0;
2324
+ return {
2325
+ dpop: dpopResult?.jwkThumbprint ? {
2326
+ jwkThumbprint: dpopResult.jwkThumbprint,
2327
+ jwk: dpopResult.jwk
2328
+ } : void 0,
2329
+ clientAttestation: clientAttestationResult
2330
+ };
2331
+ }
2332
+ async function verifyAuthorizationRequestClientAttestation(options, authorizationServerMetadata, callbacks, dpopJwkThumbprint, now, requestClientId) {
2333
+ if (!options.clientAttestationJwt || !options.clientAttestationPopJwt) {
2334
+ if (!options.required && !options.clientAttestationJwt && !options.clientAttestationPopJwt) {
2335
+ return void 0;
2336
+ }
2337
+ throw new Oauth2ServerErrorResponseError({
2338
+ error: "invalid_dpop_proof" /* InvalidDpopProof */,
2339
+ error_description: `Missing required client attestation parameters in pushed authorization request. Make sure to provide the '${oauthClientAttestationHeader}' and '${oauthClientAttestationPopHeader}' header values.`
2340
+ });
2341
+ }
2342
+ const verifiedClientAttestation = await verifyClientAttestation({
2343
+ authorizationServer: authorizationServerMetadata.issuer,
2344
+ callbacks,
2345
+ clientAttestationJwt: options.clientAttestationJwt,
2346
+ clientAttestationPopJwt: options.clientAttestationPopJwt,
2347
+ now
2045
2348
  });
2046
- if (payload.iss !== options.clientAttestation.payload.sub) {
2047
- throw new Oauth2Error(
2048
- `Client Attestation Pop jwt contains 'iss' (client_id) value '${payload.iss}', but expected 'sub' value from client attestation '${options.clientAttestation.payload.sub}'`
2349
+ if (requestClientId && requestClientId !== verifiedClientAttestation.clientAttestation.payload.sub) {
2350
+ throw new Oauth2ServerErrorResponseError(
2351
+ {
2352
+ error: "invalid_client" /* InvalidClient */,
2353
+ error_description: `The client_id '${requestClientId}' in the request does not match the client id '${verifiedClientAttestation.clientAttestation.payload.sub}' in the client attestation`
2354
+ },
2355
+ {
2356
+ status: 401
2357
+ }
2049
2358
  );
2050
2359
  }
2051
- if (payload.aud !== options.authorizationServer) {
2052
- throw new Oauth2Error(
2053
- `Client Attestation Pop jwt contains 'aud' value '${payload.aud}', but expected authorization server identifier '${options.authorizationServer}'`
2054
- );
2360
+ if (options.ensureConfirmationKeyMatchesDpopKey && dpopJwkThumbprint) {
2361
+ const clientAttestationJkt = await calculateJwkThumbprint({
2362
+ hashAlgorithm: "sha-256" /* Sha256 */,
2363
+ hashCallback: callbacks.hash,
2364
+ jwk: verifiedClientAttestation.clientAttestation.payload.cnf.jwk
2365
+ });
2366
+ if (clientAttestationJkt !== dpopJwkThumbprint) {
2367
+ throw new Oauth2ServerErrorResponseError(
2368
+ {
2369
+ error: "invalid_request" /* InvalidRequest */,
2370
+ error_description: "Expected the DPoP JWK thumbprint value to match the JWK thumbprint of the client attestation confirmation JWK. Ensrue both DPoP and client attestation use the same key."
2371
+ },
2372
+ {
2373
+ status: 401
2374
+ }
2375
+ );
2376
+ }
2377
+ }
2378
+ return verifiedClientAttestation;
2379
+ }
2380
+ async function verifyAuthorizationRequestDpop(options, request, callbacks, now) {
2381
+ if (options.required && !options.jwt && !options.jwkThumbprint) {
2382
+ throw new Oauth2ServerErrorResponseError({
2383
+ error: "invalid_dpop_proof" /* InvalidDpopProof */,
2384
+ error_description: `Missing required DPoP parameters in authorization request. Either DPoP header or 'dpop_jkt' is required.`
2385
+ });
2386
+ }
2387
+ const verifyDpopResult = options.jwt ? await verifyDpopJwt({
2388
+ callbacks,
2389
+ dpopJwt: options.jwt,
2390
+ request,
2391
+ allowedSigningAlgs: options.allowedSigningAlgs,
2392
+ now
2393
+ }) : void 0;
2394
+ if (options.jwkThumbprint && verifyDpopResult && options.jwkThumbprint !== verifyDpopResult.jwkThumbprint) {
2395
+ throw new Oauth2ServerErrorResponseError({
2396
+ error: "invalid_dpop_proof" /* InvalidDpopProof */,
2397
+ error_description: `DPoP jwk thumbprint does not match with 'dpop_jkt' provided in authorization request`
2398
+ });
2055
2399
  }
2056
- const { signer } = await verifyJwt({
2057
- signer: {
2058
- alg: header.alg,
2059
- method: "jwk",
2060
- publicJwk: options.clientAttestation.payload.cnf.jwk
2061
- },
2062
- now: options.now,
2063
- header,
2064
- expectedNonce: options.expectedNonce,
2065
- payload,
2066
- compact: options.clientAttestationPopJwt,
2067
- verifyJwtCallback: options.callbacks.verifyJwt,
2068
- errorMessage: "client attestation pop jwt verification failed"
2069
- });
2070
2400
  return {
2071
- header,
2072
- payload,
2073
- signer
2401
+ jwk: verifyDpopResult?.header.jwk,
2402
+ jwkThumbprint: verifyDpopResult?.jwkThumbprint ?? options.jwkThumbprint
2074
2403
  };
2075
2404
  }
2076
- async function createClientAttestationPopJwt(options) {
2077
- const header = (0, import_utils33.parseWithErrorHandling)(zClientAttestationPopJwtHeader, {
2078
- typ: "oauth-client-attestation-pop+jwt",
2079
- alg: options.signer.alg
2405
+
2406
+ // src/authorization-challenge/verify-authorization-challenge-request.ts
2407
+ async function verifyAuthorizationChallengeRequest(options) {
2408
+ const { clientAttestation, dpop } = await verifyAuthorizationRequest({
2409
+ ...options,
2410
+ authorizationRequest: options.authorizationChallengeRequest
2080
2411
  });
2081
- const clientAttestation = decodeJwt({
2082
- jwt: options.clientAttestation,
2083
- headerSchema: zClientAttestationJwtHeader,
2084
- payloadSchema: zClientAttestationJwtPayload
2412
+ return {
2413
+ dpop,
2414
+ clientAttestation
2415
+ };
2416
+ }
2417
+
2418
+ // src/authorization-request/create-pushed-authorization-response.ts
2419
+ var import_utils35 = require("@openid4vc/utils");
2420
+ function createPushedAuthorizationResponse(options) {
2421
+ const pushedAuthorizationResponse = (0, import_utils35.parseWithErrorHandling)(zPushedAuthorizationResponse, {
2422
+ ...options.additionalPayload,
2423
+ expires_in: options.expiresInSeconds,
2424
+ request_uri: options.requestUri
2085
2425
  });
2086
- const expiresAt = options.expiresAt ?? (0, import_utils33.addSecondsToDate)(options.issuedAt ?? /* @__PURE__ */ new Date(), 1 * 60);
2087
- const payload = (0, import_utils33.parseWithErrorHandling)(zClientAttestationPopJwtPayload, {
2088
- aud: options.authorizationServer,
2089
- iss: clientAttestation.payload.sub,
2090
- iat: (0, import_utils33.dateToSeconds)(options.issuedAt),
2091
- exp: (0, import_utils33.dateToSeconds)(expiresAt),
2092
- jti: (0, import_utils33.encodeToBase64Url)(await options.callbacks.generateRandom(32)),
2093
- nonce: options.nonce,
2094
- ...options.additionalPayload
2426
+ return { pushedAuthorizationResponse };
2427
+ }
2428
+ function createPushedAuthorizationErrorResponse(options) {
2429
+ const pushedAuthorizationErrorResponse = (0, import_utils35.parseWithErrorHandling)(zAccessTokenErrorResponse, {
2430
+ ...options.additionalPayload,
2431
+ error: options.error,
2432
+ error_description: options.errorDescription
2095
2433
  });
2096
- const { jwt } = await options.callbacks.signJwt(options.signer, {
2097
- header,
2098
- payload
2434
+ return pushedAuthorizationErrorResponse;
2435
+ }
2436
+
2437
+ // src/authorization-request/parse-pushed-authorization-request.ts
2438
+ var import_utils36 = require("@openid4vc/utils");
2439
+ function parsePushedAuthorizationRequest(options) {
2440
+ const parsedAuthorizationRequest = zAuthorizationRequest.safeParse(options.authorizationRequest);
2441
+ if (!parsedAuthorizationRequest.success) {
2442
+ throw new Oauth2ServerErrorResponseError({
2443
+ error: "invalid_request" /* InvalidRequest */,
2444
+ error_description: `Error occured during validation of pushed authorization request.
2445
+ ${(0, import_utils36.formatZodError)(parsedAuthorizationRequest.error)}`
2446
+ });
2447
+ }
2448
+ const authorizationRequest = parsedAuthorizationRequest.data;
2449
+ const { clientAttestation, dpop } = parseAuthorizationRequest({
2450
+ authorizationRequest,
2451
+ request: options.request
2099
2452
  });
2100
- return jwt;
2453
+ return {
2454
+ authorizationRequest,
2455
+ dpop,
2456
+ clientAttestation
2457
+ };
2458
+ }
2459
+
2460
+ // src/authorization-request/verify-pushed-authorization-request.ts
2461
+ async function verifyPushedAuthorizationRequest(options) {
2462
+ const { clientAttestation, dpop } = await verifyAuthorizationRequest(options);
2463
+ return {
2464
+ dpop,
2465
+ clientAttestation
2466
+ };
2101
2467
  }
2102
2468
 
2103
2469
  // src/Oauth2AuthorizationServer.ts
@@ -2106,7 +2472,7 @@ var Oauth2AuthorizationServer = class {
2106
2472
  this.options = options;
2107
2473
  }
2108
2474
  createAuthorizationServerMetadata(authorizationServerMetadata) {
2109
- return (0, import_utils34.parseWithErrorHandling)(
2475
+ return (0, import_utils37.parseWithErrorHandling)(
2110
2476
  zAuthorizationServerMetadata,
2111
2477
  authorizationServerMetadata,
2112
2478
  "Error validating authorization server metadata"
@@ -2151,7 +2517,7 @@ var Oauth2AuthorizationServer = class {
2151
2517
  scope: options.scope,
2152
2518
  clientId: options.clientId,
2153
2519
  signer: options.signer,
2154
- dpopJwk: options.dpopJwk,
2520
+ dpop: options.dpop,
2155
2521
  now: options.now,
2156
2522
  additionalPayload: options.additionalAccessTokenPayload
2157
2523
  });
@@ -2159,23 +2525,47 @@ var Oauth2AuthorizationServer = class {
2159
2525
  accessToken,
2160
2526
  callbacks: this.options.callbacks,
2161
2527
  expiresInSeconds: options.expiresInSeconds,
2162
- tokenType: options.dpopJwk ? "DPoP" : "Bearer",
2528
+ tokenType: options.dpop ? "DPoP" : "Bearer",
2163
2529
  cNonce: options.cNonce,
2164
2530
  cNonceExpiresIn: options.cNonceExpiresIn,
2165
2531
  additionalPayload: options.additionalAccessTokenResponsePayload
2166
2532
  });
2167
2533
  }
2534
+ /**
2535
+ * Parse a pushed authorization request
2536
+ */
2537
+ parsePushedAuthorizationRequest(options) {
2538
+ return parsePushedAuthorizationRequest(options);
2539
+ }
2540
+ verifyPushedAuthorizationRequest(options) {
2541
+ return verifyPushedAuthorizationRequest({
2542
+ ...options,
2543
+ callbacks: this.options.callbacks
2544
+ });
2545
+ }
2546
+ createPushedAuthorizationResponse(options) {
2547
+ return createPushedAuthorizationResponse(options);
2548
+ }
2549
+ createPushedAuthorizationErrorResponse(options) {
2550
+ return createPushedAuthorizationErrorResponse(options);
2551
+ }
2168
2552
  /**
2169
2553
  * Parse an authorization challenge request
2170
2554
  */
2171
2555
  parseAuthorizationChallengeRequest(options) {
2172
2556
  return parseAuthorizationChallengeRequest(options);
2173
2557
  }
2558
+ verifyAuthorizationChallengeRequest(options) {
2559
+ return verifyAuthorizationChallengeRequest({
2560
+ ...options,
2561
+ callbacks: this.options.callbacks
2562
+ });
2563
+ }
2174
2564
  createAuthorizationChallengeResponse(options) {
2175
2565
  return createAuthorizationChallengeResponse(options);
2176
2566
  }
2177
2567
  /**
2178
- * Create an authorization challenge error response indicating presentation of credenitals
2568
+ * Create an authorization challenge error response indicating presentation of credentials
2179
2569
  * using OpenID4VP is required before authorization can be granted.
2180
2570
  *
2181
2571
  * The `presentation` parameter should be an OpenID4VP authorization request url.
@@ -2193,34 +2583,26 @@ var Oauth2AuthorizationServer = class {
2193
2583
  createAuthorizationChallengeErrorResponse(options) {
2194
2584
  return createAuthorizationChallengeErrorResponse(options);
2195
2585
  }
2196
- async verifyClientAttestation({
2197
- authorizationServer,
2198
- headers
2199
- }) {
2200
- const { clientAttestationHeader, clientAttestationPopHeader } = extractClientAttestationJwtsFromHeaders(headers);
2201
- const clientAttestation = await verifyClientAttestationJwt({
2202
- callbacks: this.options.callbacks,
2203
- clientAttestationJwt: clientAttestationHeader
2586
+ async verifyDpopJwt(options) {
2587
+ return verifyDpopJwt({
2588
+ ...options,
2589
+ callbacks: this.options.callbacks
2204
2590
  });
2205
- const clientAttestationPop = await verifyClientAttestationPopJwt({
2206
- callbacks: this.options.callbacks,
2207
- authorizationServer,
2208
- clientAttestation,
2209
- clientAttestationPopJwt: clientAttestationPopHeader
2591
+ }
2592
+ async verifyClientAttestation(options) {
2593
+ return verifyClientAttestation({
2594
+ ...options,
2595
+ callbacks: this.options.callbacks
2210
2596
  });
2211
- return {
2212
- clientAttestation,
2213
- clientAttestationPop
2214
- };
2215
2597
  }
2216
2598
  };
2217
2599
 
2218
2600
  // src/Oauth2Client.ts
2219
- var import_utils41 = require("@openid4vc/utils");
2601
+ var import_utils44 = require("@openid4vc/utils");
2220
2602
 
2221
2603
  // src/access-token/retrieve-access-token.ts
2222
- var import_utils35 = require("@openid4vc/utils");
2223
- var import_utils36 = require("@openid4vc/utils");
2604
+ var import_utils38 = require("@openid4vc/utils");
2605
+ var import_utils39 = require("@openid4vc/utils");
2224
2606
  async function retrievePreAuthorizedCodeAccessToken(options) {
2225
2607
  const request = {
2226
2608
  grant_type: preAuthorizedCodeGrantIdentifier,
@@ -2234,8 +2616,7 @@ async function retrievePreAuthorizedCodeAccessToken(options) {
2234
2616
  request,
2235
2617
  dpop: options.dpop,
2236
2618
  callbacks: options.callbacks,
2237
- resource: options.resource,
2238
- clientAttestation: options.clientAttestation
2619
+ resource: options.resource
2239
2620
  });
2240
2621
  }
2241
2622
  async function retrieveAuthorizationCodeAccessToken(options) {
@@ -2252,8 +2633,7 @@ async function retrieveAuthorizationCodeAccessToken(options) {
2252
2633
  request,
2253
2634
  dpop: options.dpop,
2254
2635
  resource: options.resource,
2255
- callbacks: options.callbacks,
2256
- clientAttestation: options.clientAttestation
2636
+ callbacks: options.callbacks
2257
2637
  });
2258
2638
  }
2259
2639
  async function retrieveRefreshTokenAccessToken(options) {
@@ -2268,13 +2648,12 @@ async function retrieveRefreshTokenAccessToken(options) {
2268
2648
  request,
2269
2649
  dpop: options.dpop,
2270
2650
  callbacks: options.callbacks,
2271
- resource: options.resource,
2272
- clientAttestation: options.clientAttestation
2651
+ resource: options.resource
2273
2652
  });
2274
2653
  }
2275
2654
  async function retrieveAccessToken(options) {
2276
- const fetchWithZod = (0, import_utils35.createZodFetcher)(options.callbacks.fetch);
2277
- const accessTokenRequest = (0, import_utils35.parseWithErrorHandling)(
2655
+ const fetchWithZod = (0, import_utils38.createZodFetcher)(options.callbacks.fetch);
2656
+ const accessTokenRequest = (0, import_utils38.parseWithErrorHandling)(
2278
2657
  zAccessTokenRequest,
2279
2658
  options.request,
2280
2659
  "Error validating access token request"
@@ -2282,11 +2661,6 @@ async function retrieveAccessToken(options) {
2282
2661
  if (accessTokenRequest.tx_code) {
2283
2662
  accessTokenRequest.user_pin = accessTokenRequest.tx_code;
2284
2663
  }
2285
- const clientAttestation = options.clientAttestation ? await createClientAttestationForRequest({
2286
- authorizationServer: options.authorizationServerMetadata.issuer,
2287
- clientAttestation: options.clientAttestation,
2288
- callbacks: options.callbacks
2289
- }) : void 0;
2290
2664
  return await authorizationServerRequestWithDpopRetry({
2291
2665
  dpop: options.dpop,
2292
2666
  request: async (dpop) => {
@@ -2299,22 +2673,26 @@ async function retrieveAccessToken(options) {
2299
2673
  callbacks: options.callbacks,
2300
2674
  nonce: dpop.nonce
2301
2675
  }) : void 0;
2302
- const requestQueryParams = (0, import_utils35.objectToQueryParams)({
2303
- ...accessTokenRequest,
2304
- ...clientAttestation?.body
2676
+ const headers = new import_utils38.Headers({
2677
+ "Content-Type": import_utils38.ContentType.XWwwFormUrlencoded,
2678
+ ...dpopHeaders
2679
+ });
2680
+ await options.callbacks.clientAuthentication({
2681
+ url: options.authorizationServerMetadata.token_endpoint,
2682
+ method: "POST",
2683
+ authorizationServerMetadata: options.authorizationServerMetadata,
2684
+ body: accessTokenRequest,
2685
+ contentType: import_utils38.ContentType.XWwwFormUrlencoded,
2686
+ headers
2305
2687
  });
2306
2688
  const { response, result } = await fetchWithZod(
2307
2689
  zAccessTokenResponse,
2308
- import_utils35.ContentType.Json,
2690
+ import_utils38.ContentType.Json,
2309
2691
  options.authorizationServerMetadata.token_endpoint,
2310
2692
  {
2311
- body: requestQueryParams.toString(),
2693
+ body: (0, import_utils38.objectToQueryParams)(accessTokenRequest).toString(),
2312
2694
  method: "POST",
2313
- headers: {
2314
- "Content-Type": import_utils35.ContentType.XWwwFormUrlencoded,
2315
- ...clientAttestation?.headers,
2316
- ...dpopHeaders
2317
- }
2695
+ headers
2318
2696
  }
2319
2697
  );
2320
2698
  if (!response.ok || !result) {
@@ -2328,7 +2706,7 @@ async function retrieveAccessToken(options) {
2328
2706
  response
2329
2707
  );
2330
2708
  }
2331
- throw new import_utils36.InvalidFetchResponseError(
2709
+ throw new import_utils39.InvalidFetchResponseError(
2332
2710
  `Unable to retrieve access token from '${options.authorizationServerMetadata.token_endpoint}'. Received response with status ${response.status}`,
2333
2711
  await response.clone().text(),
2334
2712
  response
@@ -2350,10 +2728,10 @@ async function retrieveAccessToken(options) {
2350
2728
  }
2351
2729
 
2352
2730
  // src/authorization-challenge/send-authorization-challenge.ts
2353
- var import_utils37 = require("@openid4vc/utils");
2354
- var import_utils38 = require("@openid4vc/utils");
2731
+ var import_utils40 = require("@openid4vc/utils");
2732
+ var import_utils41 = require("@openid4vc/utils");
2355
2733
  async function sendAuthorizationChallengeRequest(options) {
2356
- const fetchWithZod = (0, import_utils37.createZodFetcher)(options.callbacks.fetch);
2734
+ const fetchWithZod = (0, import_utils40.createZodFetcher)(options.callbacks.fetch);
2357
2735
  const authorizationServerMetadata = options.authorizationServerMetadata;
2358
2736
  const authorizationChallengeEndpoint = authorizationServerMetadata.authorization_challenge_endpoint;
2359
2737
  if (!authorizationChallengeEndpoint) {
@@ -2366,21 +2744,14 @@ async function sendAuthorizationChallengeRequest(options) {
2366
2744
  callbacks: options.callbacks,
2367
2745
  codeVerifier: options.pkceCodeVerifier
2368
2746
  }) : void 0;
2369
- const clientAttestation = options.clientAttestation ? await createClientAttestationForRequest({
2370
- authorizationServer: options.authorizationServerMetadata.issuer,
2371
- clientAttestation: options.clientAttestation,
2372
- callbacks: options.callbacks
2373
- }) : void 0;
2374
- const authorizationChallengeRequest = (0, import_utils37.parseWithErrorHandling)(zAuthorizationChallengeRequest, {
2747
+ const authorizationChallengeRequest = (0, import_utils40.parseWithErrorHandling)(zAuthorizationChallengeRequest, {
2375
2748
  ...options.additionalRequestPayload,
2376
2749
  auth_session: options.authSession,
2377
- client_id: options.clientId,
2378
2750
  scope: options.scope,
2379
2751
  resource: options.resource,
2380
2752
  code_challenge: pkce?.codeChallenge,
2381
2753
  code_challenge_method: pkce?.codeChallengeMethod,
2382
- presentation_during_issuance_session: options.presentationDuringIssuanceSession,
2383
- ...clientAttestation?.body
2754
+ presentation_during_issuance_session: options.presentationDuringIssuanceSession
2384
2755
  });
2385
2756
  return authorizationServerRequestWithDpopRetry({
2386
2757
  dpop: options.dpop,
@@ -2394,18 +2765,26 @@ async function sendAuthorizationChallengeRequest(options) {
2394
2765
  callbacks: options.callbacks,
2395
2766
  nonce: dpop.nonce
2396
2767
  }) : void 0;
2768
+ const headers = new import_utils40.Headers({
2769
+ ...dpopHeaders,
2770
+ "Content-Type": import_utils40.ContentType.XWwwFormUrlencoded
2771
+ });
2772
+ await options.callbacks.clientAuthentication({
2773
+ url: authorizationChallengeEndpoint,
2774
+ method: "POST",
2775
+ authorizationServerMetadata: options.authorizationServerMetadata,
2776
+ body: authorizationChallengeRequest,
2777
+ contentType: import_utils40.ContentType.XWwwFormUrlencoded,
2778
+ headers
2779
+ });
2397
2780
  const { response, result } = await fetchWithZod(
2398
2781
  zAuthorizationChallengeResponse,
2399
- import_utils37.ContentType.Json,
2782
+ import_utils40.ContentType.Json,
2400
2783
  authorizationChallengeEndpoint,
2401
2784
  {
2402
2785
  method: "POST",
2403
- body: (0, import_utils37.objectToQueryParams)(authorizationChallengeRequest).toString(),
2404
- headers: {
2405
- ...clientAttestation?.headers,
2406
- ...dpopHeaders,
2407
- "Content-Type": import_utils37.ContentType.XWwwFormUrlencoded
2408
- }
2786
+ body: (0, import_utils40.objectToQueryParams)(authorizationChallengeRequest).toString(),
2787
+ headers
2409
2788
  }
2410
2789
  );
2411
2790
  if (!response.ok || !result) {
@@ -2419,14 +2798,14 @@ async function sendAuthorizationChallengeRequest(options) {
2419
2798
  response
2420
2799
  );
2421
2800
  }
2422
- throw new import_utils38.InvalidFetchResponseError(
2801
+ throw new import_utils41.InvalidFetchResponseError(
2423
2802
  `Error requesting authorization code from authorization challenge endpoint '${authorizationServerMetadata.authorization_challenge_endpoint}'. Received response with status ${response.status}`,
2424
2803
  await response.clone().text(),
2425
2804
  response
2426
2805
  );
2427
2806
  }
2428
2807
  if (!result.success) {
2429
- throw new import_utils37.ValidationError("Error validating authorization challenge response", result.error);
2808
+ throw new import_utils40.ValidationError("Error validating authorization challenge response", result.error);
2430
2809
  }
2431
2810
  const dpopNonce = extractDpopNonceFromHeaders(response.headers) ?? void 0;
2432
2811
  return {
@@ -2442,8 +2821,8 @@ async function sendAuthorizationChallengeRequest(options) {
2442
2821
  }
2443
2822
 
2444
2823
  // src/authorization-request/create-authorization-request.ts
2445
- var import_utils39 = require("@openid4vc/utils");
2446
- var import_utils40 = require("@openid4vc/utils");
2824
+ var import_utils42 = require("@openid4vc/utils");
2825
+ var import_utils43 = require("@openid4vc/utils");
2447
2826
  async function createAuthorizationRequestUrl(options) {
2448
2827
  const authorizationServerMetadata = options.authorizationServerMetadata;
2449
2828
  const pushedAuthorizationRequestEndpoint = authorizationServerMetadata.pushed_authorization_request_endpoint;
@@ -2475,11 +2854,6 @@ async function createAuthorizationRequestUrl(options) {
2475
2854
  `Authorization server '${authorizationServerMetadata.issuer}' indicated that pushed authorization requests are required, but the 'pushed_authorization_request_endpoint' is missing in the authorization server metadata.`
2476
2855
  );
2477
2856
  }
2478
- const clientAttestation = options.clientAttestation ? await createClientAttestationForRequest({
2479
- authorizationServer: options.authorizationServerMetadata.issuer,
2480
- clientAttestation: options.clientAttestation,
2481
- callbacks: options.callbacks
2482
- }) : void 0;
2483
2857
  const { pushedAuthorizationResponse, dpopNonce } = await authorizationServerRequestWithDpopRetry({
2484
2858
  dpop: options.dpop,
2485
2859
  request: async (dpop2) => {
@@ -2493,16 +2867,11 @@ async function createAuthorizationRequestUrl(options) {
2493
2867
  nonce: dpop2.nonce
2494
2868
  }) : void 0;
2495
2869
  return await pushAuthorizationRequest({
2496
- authorizationRequest: {
2497
- ...authorizationRequest,
2498
- ...clientAttestation?.headers
2499
- },
2870
+ authorizationServerMetadata,
2871
+ authorizationRequest,
2500
2872
  pushedAuthorizationRequestEndpoint,
2501
- fetch: options.callbacks.fetch,
2502
- headers: {
2503
- ...clientAttestation?.headers,
2504
- ...dpopHeaders
2505
- }
2873
+ callbacks: options.callbacks,
2874
+ headers: dpopHeaders
2506
2875
  });
2507
2876
  }
2508
2877
  });
@@ -2525,7 +2894,7 @@ async function createAuthorizationRequestUrl(options) {
2525
2894
  });
2526
2895
  }
2527
2896
  }
2528
- const authorizationRequestUrl = `${authorizationServerMetadata.authorization_endpoint}?${(0, import_utils39.objectToQueryParams)(pushedAuthorizationRequest ?? authorizationRequest).toString()}`;
2897
+ const authorizationRequestUrl = `${authorizationServerMetadata.authorization_endpoint}?${(0, import_utils42.objectToQueryParams)(pushedAuthorizationRequest ?? authorizationRequest).toString()}`;
2529
2898
  return {
2530
2899
  authorizationRequestUrl,
2531
2900
  pkce,
@@ -2533,23 +2902,32 @@ async function createAuthorizationRequestUrl(options) {
2533
2902
  };
2534
2903
  }
2535
2904
  async function pushAuthorizationRequest(options) {
2536
- const fetchWithZod = (0, import_utils39.createZodFetcher)(options.fetch);
2905
+ const fetchWithZod = (0, import_utils42.createZodFetcher)(options.callbacks.fetch);
2537
2906
  if (options.authorizationRequest.request_uri) {
2538
2907
  throw new Oauth2Error(
2539
2908
  `Authorization request contains 'request_uri' parameter. This is not allowed for pushed authorization reuqests.`
2540
2909
  );
2541
2910
  }
2911
+ const headers = new import_utils42.Headers({
2912
+ ...options.headers,
2913
+ "Content-Type": import_utils42.ContentType.XWwwFormUrlencoded
2914
+ });
2915
+ await options.callbacks.clientAuthentication({
2916
+ url: options.pushedAuthorizationRequestEndpoint,
2917
+ method: "POST",
2918
+ authorizationServerMetadata: options.authorizationServerMetadata,
2919
+ body: options.authorizationRequest,
2920
+ contentType: import_utils42.ContentType.XWwwFormUrlencoded,
2921
+ headers
2922
+ });
2542
2923
  const { response, result } = await fetchWithZod(
2543
2924
  zPushedAuthorizationResponse,
2544
- import_utils39.ContentType.Json,
2925
+ import_utils42.ContentType.Json,
2545
2926
  options.pushedAuthorizationRequestEndpoint,
2546
2927
  {
2547
2928
  method: "POST",
2548
- body: (0, import_utils39.objectToQueryParams)(options.authorizationRequest).toString(),
2549
- headers: {
2550
- ...options.headers,
2551
- "Content-Type": import_utils39.ContentType.XWwwFormUrlencoded
2552
- }
2929
+ body: (0, import_utils42.objectToQueryParams)(options.authorizationRequest).toString(),
2930
+ headers
2553
2931
  }
2554
2932
  );
2555
2933
  if (!response.ok || !result) {
@@ -2563,7 +2941,7 @@ async function pushAuthorizationRequest(options) {
2563
2941
  response
2564
2942
  );
2565
2943
  }
2566
- throw new import_utils40.InvalidFetchResponseError(
2944
+ throw new import_utils43.InvalidFetchResponseError(
2567
2945
  `Unable to push authorization request to '${options.pushedAuthorizationRequestEndpoint}'. Received response with status ${response.status}`,
2568
2946
  await response.clone().text(),
2569
2947
  response
@@ -2584,6 +2962,8 @@ var Oauth2Client = class {
2584
2962
  constructor(options) {
2585
2963
  this.options = options;
2586
2964
  }
2965
+ // TODO: add options to provide client metadata / algs supported by the client
2966
+ // so we can find the commonly supported algs and make it easier
2587
2967
  isDpopSupported(options) {
2588
2968
  if (!options.authorizationServerMetadata.dpop_signing_alg_values_supported || options.authorizationServerMetadata.dpop_signing_alg_values_supported.length === 0) {
2589
2969
  return {
@@ -2595,6 +2975,18 @@ var Oauth2Client = class {
2595
2975
  dpopSigningAlgValuesSupported: options.authorizationServerMetadata.dpop_signing_alg_values_supported
2596
2976
  };
2597
2977
  }
2978
+ isClientAttestationSupported(options) {
2979
+ if (!options.authorizationServerMetadata.token_endpoint_auth_methods_supported || !options.authorizationServerMetadata.token_endpoint_auth_methods_supported.includes(
2980
+ "attest_jwt_client_auth" /* ClientAttestationJwt */
2981
+ )) {
2982
+ return {
2983
+ supported: false
2984
+ };
2985
+ }
2986
+ return {
2987
+ supported: true
2988
+ };
2989
+ }
2598
2990
  async fetchAuthorizationServerMetadata(issuer) {
2599
2991
  return fetchAuthorizationServerMetadata(issuer, this.options.callbacks.fetch);
2600
2992
  }
@@ -2622,18 +3014,16 @@ var Oauth2Client = class {
2622
3014
  await this.sendAuthorizationChallengeRequest({
2623
3015
  authorizationServerMetadata: options.authorizationServerMetadata,
2624
3016
  additionalRequestPayload: options.additionalRequestPayload,
2625
- clientId: options.clientId,
2626
3017
  pkceCodeVerifier: pkce?.codeVerifier,
2627
3018
  scope: options.scope,
2628
3019
  resource: options.resource,
2629
- clientAttestation: options.clientAttestation,
2630
3020
  dpop: options.dpop
2631
3021
  });
2632
3022
  } catch (error) {
2633
3023
  const isRecoverableError = error instanceof Oauth2ClientAuthorizationChallengeError && error.errorResponse.error === "redirect_to_web" /* RedirectToWeb */;
2634
3024
  if (!isRecoverableError) throw error;
2635
3025
  if (error.errorResponse.request_uri) {
2636
- const authorizationRequestUrl = `${options.authorizationServerMetadata.authorization_endpoint}?${(0, import_utils41.objectToQueryParams)(
3026
+ const authorizationRequestUrl = `${options.authorizationServerMetadata.authorization_endpoint}?${(0, import_utils44.objectToQueryParams)(
2637
3027
  {
2638
3028
  request_uri: error.errorResponse.request_uri,
2639
3029
  client_id: options.clientId
@@ -2659,7 +3049,6 @@ var Oauth2Client = class {
2659
3049
  scope: options.scope,
2660
3050
  pkceCodeVerifier: pkce?.codeVerifier,
2661
3051
  resource: options.resource,
2662
- clientAttestation: options.clientAttestation,
2663
3052
  dpop: options.dpop
2664
3053
  });
2665
3054
  }
@@ -2679,7 +3068,6 @@ var Oauth2Client = class {
2679
3068
  scope: options.scope,
2680
3069
  callbacks: this.options.callbacks,
2681
3070
  pkceCodeVerifier: options.pkceCodeVerifier,
2682
- clientAttestation: options.clientAttestation,
2683
3071
  dpop: options.dpop
2684
3072
  });
2685
3073
  }
@@ -2689,8 +3077,7 @@ var Oauth2Client = class {
2689
3077
  additionalRequestPayload,
2690
3078
  txCode,
2691
3079
  dpop,
2692
- resource,
2693
- clientAttestation
3080
+ resource
2694
3081
  }) {
2695
3082
  const result = await retrievePreAuthorizedCodeAccessToken({
2696
3083
  authorizationServerMetadata,
@@ -2702,8 +3089,7 @@ var Oauth2Client = class {
2702
3089
  tx_code: txCode
2703
3090
  },
2704
3091
  callbacks: this.options.callbacks,
2705
- dpop,
2706
- clientAttestation
3092
+ dpop
2707
3093
  });
2708
3094
  return result;
2709
3095
  }
@@ -2714,8 +3100,7 @@ var Oauth2Client = class {
2714
3100
  pkceCodeVerifier,
2715
3101
  redirectUri,
2716
3102
  resource,
2717
- dpop,
2718
- clientAttestation
3103
+ dpop
2719
3104
  }) {
2720
3105
  const result = await retrieveAuthorizationCodeAccessToken({
2721
3106
  authorizationServerMetadata,
@@ -2725,8 +3110,7 @@ var Oauth2Client = class {
2725
3110
  resource,
2726
3111
  callbacks: this.options.callbacks,
2727
3112
  dpop,
2728
- redirectUri,
2729
- clientAttestation
3113
+ redirectUri
2730
3114
  });
2731
3115
  return result;
2732
3116
  }
@@ -2735,8 +3119,7 @@ var Oauth2Client = class {
2735
3119
  additionalRequestPayload,
2736
3120
  refreshToken,
2737
3121
  resource,
2738
- dpop,
2739
- clientAttestation
3122
+ dpop
2740
3123
  }) {
2741
3124
  const result = await retrieveRefreshTokenAccessToken({
2742
3125
  authorizationServerMetadata,
@@ -2744,23 +3127,13 @@ var Oauth2Client = class {
2744
3127
  additionalRequestPayload,
2745
3128
  resource,
2746
3129
  callbacks: this.options.callbacks,
2747
- dpop,
2748
- clientAttestation
3130
+ dpop
2749
3131
  });
2750
3132
  return result;
2751
3133
  }
2752
3134
  async resourceRequest(options) {
2753
3135
  return resourceRequest(options);
2754
3136
  }
2755
- /**
2756
- * @todo move this to another class?
2757
- */
2758
- async createClientAttestationJwt(options) {
2759
- return await createClientAttestationJwt({
2760
- callbacks: this.options.callbacks,
2761
- ...options
2762
- });
2763
- }
2764
3137
  };
2765
3138
 
2766
3139
  // src/Oauth2ResourceServer.ts
@@ -2792,12 +3165,16 @@ var Oauth2ResourceServer = class {
2792
3165
  Oauth2ServerErrorResponseError,
2793
3166
  PkceCodeChallengeMethod,
2794
3167
  SupportedAuthenticationScheme,
3168
+ SupportedClientAuthenticationMethod,
2795
3169
  authorizationCodeGrantIdentifier,
2796
3170
  calculateJwkThumbprint,
3171
+ clientAuthenticationAnonymous,
3172
+ clientAuthenticationClientAttestationJwt,
2797
3173
  clientAuthenticationClientSecretBasic,
2798
3174
  clientAuthenticationClientSecretPost,
2799
3175
  clientAuthenticationDynamic,
2800
3176
  clientAuthenticationNone,
3177
+ createClientAttestationJwt,
2801
3178
  decodeJwt,
2802
3179
  decodeJwtHeader,
2803
3180
  fetchAuthorizationServerMetadata,