@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.d.mts +2220 -492
- package/dist/index.d.ts +2220 -492
- package/dist/index.js +1105 -728
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1021 -647
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
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: () =>
|
|
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: () =>
|
|
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: () =>
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
865
|
+
var import_utils13 = require("@openid4vc/utils");
|
|
586
866
|
|
|
587
867
|
// src/metadata/fetch-well-known-metadata.ts
|
|
588
|
-
var
|
|
589
|
-
var
|
|
868
|
+
var import_utils10 = require("@openid4vc/utils");
|
|
869
|
+
var import_utils11 = require("@openid4vc/utils");
|
|
590
870
|
|
|
591
|
-
// ../utils/src/error
|
|
592
|
-
var
|
|
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
|
-
|
|
600
|
-
|
|
601
|
-
|
|
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
|
-
|
|
604
|
-
if (
|
|
605
|
-
return
|
|
886
|
+
return path.reduce((acc, item) => {
|
|
887
|
+
if (typeof item === "number") {
|
|
888
|
+
return `${acc}[${item.toString()}]`;
|
|
606
889
|
}
|
|
607
|
-
|
|
608
|
-
|
|
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 (
|
|
633
|
-
return [
|
|
634
|
-
constants.issueSeparator
|
|
635
|
-
);
|
|
893
|
+
if (!constants.identifierRegex.test(item)) {
|
|
894
|
+
return `${acc}["${item}"]`;
|
|
636
895
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
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 =
|
|
941
|
+
const formattedError = formatZodError(zodError);
|
|
660
942
|
this.message = `${message}
|
|
661
|
-
|
|
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,
|
|
673
|
-
const { result, response } = await fetcher(schema,
|
|
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
|
|
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
|
|
692
|
-
var
|
|
693
|
-
var
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
705
|
-
pushed_authorization_request_endpoint:
|
|
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:
|
|
708
|
-
introspection_endpoint_auth_methods_supported:
|
|
709
|
-
|
|
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:
|
|
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:
|
|
1002
|
+
authorization_challenge_endpoint: import_zod9.default.optional(import_utils12.zHttpsUrl),
|
|
714
1003
|
// From OpenID4VCI specification
|
|
715
|
-
pre_authorized_grant_anonymous_access_supported:
|
|
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,
|
|
733
|
-
const parsedIssuerUrl = new
|
|
734
|
-
const authorizationServerWellKnownMetadataUrl = (0,
|
|
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,
|
|
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
|
|
794
|
-
var
|
|
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,
|
|
797
|
-
const { result, response } = await fetcher(zJwkSet,
|
|
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
|
|
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
|
|
866
|
-
var
|
|
867
|
-
var zAccessTokenProfileJwtHeader =
|
|
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:
|
|
1107
|
+
typ: import_zod10.default.enum(["application/at+jwt", "at+jwt"])
|
|
870
1108
|
}).passthrough();
|
|
871
|
-
var zAccessTokenProfileJwtPayload =
|
|
1109
|
+
var zAccessTokenProfileJwtPayload = import_zod10.default.object({
|
|
872
1110
|
...zJwtPayload.shape,
|
|
873
|
-
iss:
|
|
874
|
-
exp:
|
|
875
|
-
iat:
|
|
876
|
-
aud:
|
|
877
|
-
sub:
|
|
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:
|
|
880
|
-
jti:
|
|
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:
|
|
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
|
|
1171
|
+
var import_utils19 = require("@openid4vc/utils");
|
|
934
1172
|
|
|
935
1173
|
// src/dpop/dpop.ts
|
|
936
|
-
var
|
|
1174
|
+
var import_utils18 = require("@openid4vc/utils");
|
|
937
1175
|
|
|
938
1176
|
// src/dpop/z-dpop.ts
|
|
939
|
-
var
|
|
940
|
-
var
|
|
941
|
-
var zDpopJwtPayload =
|
|
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:
|
|
944
|
-
htu:
|
|
945
|
-
htm:
|
|
946
|
-
jti:
|
|
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:
|
|
1186
|
+
ath: import_zod11.default.optional(import_zod11.default.string())
|
|
949
1187
|
}).passthrough();
|
|
950
|
-
var zDpopJwtHeader =
|
|
1188
|
+
var zDpopJwtHeader = import_zod11.default.object({
|
|
951
1189
|
...zJwtHeader.shape,
|
|
952
|
-
typ:
|
|
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,
|
|
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,
|
|
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,
|
|
1211
|
+
const payload = (0, import_utils18.parseWithErrorHandling)(zDpopJwtPayload, {
|
|
974
1212
|
htu: htuFromRequestUrl(options.request.url),
|
|
975
|
-
iat: (0,
|
|
1213
|
+
iat: (0, import_utils18.dateToSeconds)(options.issuedAt),
|
|
976
1214
|
htm: options.request.method,
|
|
977
|
-
jti: (0,
|
|
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
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
if (
|
|
1001
|
-
|
|
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 (
|
|
1250
|
+
if (options.request.method !== payload.htm) {
|
|
1004
1251
|
throw new Oauth2Error(
|
|
1005
|
-
`Dpop jwt contains
|
|
1252
|
+
`Dpop jwt contains htm value '${payload.htm}', but expected htm value '${options.request.method}'`
|
|
1006
1253
|
);
|
|
1007
1254
|
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
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 (
|
|
1026
|
-
|
|
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 !==
|
|
1275
|
+
if (options.expectedJwkThumbprint && options.expectedJwkThumbprint !== jwkThumbprint) {
|
|
1036
1276
|
throw new Oauth2Error(
|
|
1037
|
-
`Dpop is signed with jwk with thumbprint value '${
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
1444
|
+
var import_utils24 = require("@openid4vc/utils");
|
|
1193
1445
|
|
|
1194
1446
|
// src/access-token/introspect-token.ts
|
|
1195
|
-
var
|
|
1196
|
-
var
|
|
1197
|
-
var
|
|
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
|
|
1201
|
-
var
|
|
1202
|
-
var zTokenIntrospectionRequest =
|
|
1203
|
-
token:
|
|
1204
|
-
token_type_hint:
|
|
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 =
|
|
1207
|
-
active:
|
|
1208
|
-
scope:
|
|
1209
|
-
client_id:
|
|
1210
|
-
username:
|
|
1211
|
-
token_type:
|
|
1212
|
-
exp:
|
|
1213
|
-
iat:
|
|
1214
|
-
nbf:
|
|
1215
|
-
sub:
|
|
1216
|
-
aud:
|
|
1217
|
-
iss:
|
|
1218
|
-
jti:
|
|
1219
|
-
cnf:
|
|
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,
|
|
1225
|
-
const introspectionRequest = (0,
|
|
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
|
|
1235
|
-
"Content-Type":
|
|
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
|
-
|
|
1492
|
+
authorizationServerMetadata: options.authorizationServerMetadata,
|
|
1241
1493
|
body: introspectionRequest,
|
|
1242
|
-
contentType:
|
|
1494
|
+
contentType: import_utils21.ContentType.XWwwFormUrlencoded,
|
|
1243
1495
|
headers
|
|
1244
1496
|
});
|
|
1245
1497
|
const { result, response } = await fetchWithZod(
|
|
1246
1498
|
zTokenIntrospectionResponse,
|
|
1247
|
-
|
|
1499
|
+
import_utils21.ContentType.Json,
|
|
1248
1500
|
introspectionEndpoint,
|
|
1249
1501
|
{
|
|
1250
|
-
body: (0,
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
1440
|
-
const endpointType = url ===
|
|
1441
|
-
const method = getSupportedClientAuthenticationMethod(
|
|
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,
|
|
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
|
|
1765
|
+
var import_utils37 = require("@openid4vc/utils");
|
|
1474
1766
|
|
|
1475
1767
|
// src/access-token/create-access-token.ts
|
|
1476
|
-
var
|
|
1768
|
+
var import_utils26 = require("@openid4vc/utils");
|
|
1477
1769
|
async function createAccessTokenJwt(options) {
|
|
1478
|
-
const header = (0,
|
|
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,
|
|
1484
|
-
iat: (0,
|
|
1485
|
-
exp: (0,
|
|
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,
|
|
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.
|
|
1784
|
+
cnf: options.dpop ? {
|
|
1493
1785
|
jkt: await calculateJwkThumbprint({
|
|
1494
1786
|
hashAlgorithm: "sha-256" /* Sha256 */,
|
|
1495
1787
|
hashCallback: options.callbacks.hash,
|
|
1496
|
-
jwk: options.
|
|
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
|
|
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
|
|
1528
|
-
|
|
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":
|
|
1811
|
+
"pre-authorized_code": import_zod14.default.optional(import_zod14.default.string()),
|
|
1531
1812
|
// Authorization code flow
|
|
1532
|
-
code:
|
|
1533
|
-
redirect_uri:
|
|
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:
|
|
1536
|
-
resource:
|
|
1537
|
-
code_verifier:
|
|
1538
|
-
grant_type:
|
|
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
|
-
|
|
1824
|
+
import_zod14.default.string()
|
|
1544
1825
|
])
|
|
1545
1826
|
}).passthrough(),
|
|
1546
|
-
|
|
1547
|
-
tx_code:
|
|
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:
|
|
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 =
|
|
1560
|
-
access_token:
|
|
1561
|
-
token_type:
|
|
1562
|
-
expires_in:
|
|
1563
|
-
scope:
|
|
1564
|
-
state:
|
|
1565
|
-
refresh_token:
|
|
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:
|
|
1568
|
-
c_nonce_expires_in:
|
|
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:
|
|
1571
|
-
|
|
1572
|
-
//
|
|
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,
|
|
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
|
-
${
|
|
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
|
-
|
|
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
|
|
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,
|
|
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,
|
|
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) :
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
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
|
-
|
|
1766
|
-
|
|
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
|
-
|
|
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
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
}
|
|
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
|
|
2175
|
+
var import_utils33 = require("@openid4vc/utils");
|
|
1827
2176
|
|
|
1828
2177
|
// src/authorization-challenge/z-authorization-challenge.ts
|
|
1829
|
-
var
|
|
1830
|
-
var
|
|
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
|
|
1834
|
-
var
|
|
1835
|
-
var zAuthorizationRequest =
|
|
1836
|
-
response_type:
|
|
1837
|
-
client_id:
|
|
1838
|
-
issuer_state:
|
|
1839
|
-
redirect_uri:
|
|
1840
|
-
resource:
|
|
1841
|
-
scope:
|
|
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:
|
|
1844
|
-
code_challenge:
|
|
1845
|
-
code_challenge_method:
|
|
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 =
|
|
1848
|
-
request_uri:
|
|
1849
|
-
client_id:
|
|
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 =
|
|
1852
|
-
request_uri:
|
|
1853
|
-
expires_in:
|
|
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 =
|
|
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:
|
|
1863
|
-
auth_session:
|
|
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:
|
|
2214
|
+
presentation_during_issuance_session: import_zod16.default.optional(import_zod16.default.string())
|
|
1866
2215
|
}).passthrough();
|
|
1867
|
-
var zAuthorizationChallengeResponse =
|
|
1868
|
-
authorization_code:
|
|
2216
|
+
var zAuthorizationChallengeResponse = import_zod16.default.object({
|
|
2217
|
+
authorization_code: import_zod16.default.string()
|
|
1869
2218
|
}).passthrough();
|
|
1870
|
-
var zAuthorizationChallengeErrorResponse =
|
|
2219
|
+
var zAuthorizationChallengeErrorResponse = import_zod16.default.object({
|
|
1871
2220
|
...zOauth2ErrorResponse.shape,
|
|
1872
|
-
auth_session:
|
|
1873
|
-
request_uri:
|
|
1874
|
-
expires_in:
|
|
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:
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
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
|
|
2249
|
+
return authorizationChallengeErrorResponse;
|
|
2002
2250
|
}
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
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
|
-
|
|
2010
|
-
|
|
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
|
-
|
|
2014
|
-
|
|
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/
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
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
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
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
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
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 (
|
|
2047
|
-
throw new
|
|
2048
|
-
|
|
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 (
|
|
2052
|
-
|
|
2053
|
-
|
|
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
|
-
|
|
2073
|
-
signer
|
|
2401
|
+
jwk: verifyDpopResult?.header.jwk,
|
|
2402
|
+
jwkThumbprint: verifyDpopResult?.jwkThumbprint ?? options.jwkThumbprint
|
|
2074
2403
|
};
|
|
2075
2404
|
}
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
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
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
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
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
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
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
|
2197
|
-
|
|
2198
|
-
|
|
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
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
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
|
|
2601
|
+
var import_utils44 = require("@openid4vc/utils");
|
|
2220
2602
|
|
|
2221
2603
|
// src/access-token/retrieve-access-token.ts
|
|
2222
|
-
var
|
|
2223
|
-
var
|
|
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,
|
|
2277
|
-
const accessTokenRequest = (0,
|
|
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
|
|
2303
|
-
|
|
2304
|
-
...
|
|
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
|
-
|
|
2690
|
+
import_utils38.ContentType.Json,
|
|
2309
2691
|
options.authorizationServerMetadata.token_endpoint,
|
|
2310
2692
|
{
|
|
2311
|
-
body:
|
|
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
|
|
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
|
|
2354
|
-
var
|
|
2731
|
+
var import_utils40 = require("@openid4vc/utils");
|
|
2732
|
+
var import_utils41 = require("@openid4vc/utils");
|
|
2355
2733
|
async function sendAuthorizationChallengeRequest(options) {
|
|
2356
|
-
const fetchWithZod = (0,
|
|
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
|
|
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
|
-
|
|
2782
|
+
import_utils40.ContentType.Json,
|
|
2400
2783
|
authorizationChallengeEndpoint,
|
|
2401
2784
|
{
|
|
2402
2785
|
method: "POST",
|
|
2403
|
-
body: (0,
|
|
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
|
|
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
|
|
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
|
|
2446
|
-
var
|
|
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
|
-
|
|
2497
|
-
|
|
2498
|
-
...clientAttestation?.headers
|
|
2499
|
-
},
|
|
2870
|
+
authorizationServerMetadata,
|
|
2871
|
+
authorizationRequest,
|
|
2500
2872
|
pushedAuthorizationRequestEndpoint,
|
|
2501
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
2925
|
+
import_utils42.ContentType.Json,
|
|
2545
2926
|
options.pushedAuthorizationRequestEndpoint,
|
|
2546
2927
|
{
|
|
2547
2928
|
method: "POST",
|
|
2548
|
-
body: (0,
|
|
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
|
|
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,
|
|
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,
|