@openid4vc/openid4vp 0.3.0-alpha-20250225204254 → 0.3.0-alpha-20250227094616
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 +74 -27
- package/dist/index.d.ts +74 -27
- package/dist/index.js +432 -265
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +366 -199
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -393,9 +393,19 @@ var zOpenid4vpAuthorizationRequest = import_zod7.z.object({
|
|
|
393
393
|
presentation_definition_uri: import_utils5.zHttpsUrl.optional(),
|
|
394
394
|
dcql_query: import_zod7.z.record(import_zod7.z.any()).optional(),
|
|
395
395
|
client_metadata: zClientMetadata.optional(),
|
|
396
|
+
client_metadata_uri: import_utils5.zHttpsUrl.optional(),
|
|
396
397
|
state: import_zod7.z.string().optional(),
|
|
397
398
|
transaction_data: import_zod7.z.array(import_zod7.z.string()).optional(),
|
|
398
|
-
trust_chain: import_zod7.z.unknown().optional()
|
|
399
|
+
trust_chain: import_zod7.z.unknown().optional(),
|
|
400
|
+
client_id_scheme: import_zod7.z.enum([
|
|
401
|
+
"pre-registered",
|
|
402
|
+
"redirect_uri",
|
|
403
|
+
"entity_id",
|
|
404
|
+
"did",
|
|
405
|
+
"verifier_attestation",
|
|
406
|
+
"x509_san_dns",
|
|
407
|
+
"x509_san_uri"
|
|
408
|
+
]).optional()
|
|
399
409
|
}).passthrough();
|
|
400
410
|
|
|
401
411
|
// src/authorization-request/z-authorization-request-dc-api.ts
|
|
@@ -412,21 +422,30 @@ var zOpenid4vpAuthorizationRequestDcApi = zOpenid4vpAuthorizationRequest.pick({
|
|
|
412
422
|
}).extend({
|
|
413
423
|
client_id: import_zod8.z.optional(import_zod8.z.string()),
|
|
414
424
|
expected_origins: import_zod8.z.array(import_zod8.z.string()).optional(),
|
|
415
|
-
response_mode: import_zod8.z.enum(["dc_api", "dc_api.jwt"])
|
|
425
|
+
response_mode: import_zod8.z.enum(["dc_api", "dc_api.jwt", "w3c_dc_api.jwt", "w3c_dc_api"]),
|
|
426
|
+
client_id_scheme: import_zod8.z.enum([
|
|
427
|
+
"pre-registered",
|
|
428
|
+
"redirect_uri",
|
|
429
|
+
"entity_id",
|
|
430
|
+
"did",
|
|
431
|
+
"verifier_attestation",
|
|
432
|
+
"x509_san_dns",
|
|
433
|
+
"x509_san_uri"
|
|
434
|
+
]).optional()
|
|
416
435
|
}).strip();
|
|
417
436
|
function isOpenid4vpAuthorizationRequestDcApi(request) {
|
|
418
|
-
return request.response_mode === "dc_api" || request.response_mode === "dc_api.jwt";
|
|
437
|
+
return request.response_mode === "dc_api" || request.response_mode === "dc_api.jwt" || request.response_mode === "w3c_dc_api.jwt" || request.response_mode === "w3c_dc_api";
|
|
419
438
|
}
|
|
420
439
|
|
|
421
440
|
// src/authorization-request/create-authorization-request.ts
|
|
422
441
|
async function createOpenid4vpAuthorizationRequest(options) {
|
|
423
|
-
const { jar, scheme = "openid4vp://",
|
|
442
|
+
const { jar, scheme = "openid4vp://", requestPayload, wallet, callbacks } = options;
|
|
424
443
|
let additionalJwtPayload;
|
|
425
444
|
let authRequestParams;
|
|
426
|
-
if (isOpenid4vpAuthorizationRequestDcApi(
|
|
445
|
+
if (isOpenid4vpAuthorizationRequestDcApi(requestPayload)) {
|
|
427
446
|
authRequestParams = (0, import_utils6.parseWithErrorHandling)(
|
|
428
447
|
zOpenid4vpAuthorizationRequestDcApi,
|
|
429
|
-
|
|
448
|
+
requestPayload,
|
|
430
449
|
"Invalid authorization request. Could not parse openid4vp dc_api authorization request."
|
|
431
450
|
);
|
|
432
451
|
if (jar && !authRequestParams.expected_origins) {
|
|
@@ -442,7 +461,7 @@ async function createOpenid4vpAuthorizationRequest(options) {
|
|
|
442
461
|
} else {
|
|
443
462
|
authRequestParams = (0, import_utils6.parseWithErrorHandling)(
|
|
444
463
|
zOpenid4vpAuthorizationRequest,
|
|
445
|
-
|
|
464
|
+
requestPayload,
|
|
446
465
|
"Invalid authorization request. Could not parse openid4vp authorization request."
|
|
447
466
|
);
|
|
448
467
|
validateOpenid4vpAuthorizationRequestPayload({ params: authRequestParams, walletVerificationOptions: wallet });
|
|
@@ -455,7 +474,7 @@ async function createOpenid4vpAuthorizationRequest(options) {
|
|
|
455
474
|
if (jar) {
|
|
456
475
|
const jarResult = await createJarAuthRequest({
|
|
457
476
|
...jar,
|
|
458
|
-
authRequestParams:
|
|
477
|
+
authRequestParams: requestPayload,
|
|
459
478
|
additionalJwtPayload,
|
|
460
479
|
callbacks
|
|
461
480
|
});
|
|
@@ -473,10 +492,10 @@ async function createOpenid4vpAuthorizationRequest(options) {
|
|
|
473
492
|
const url = new import_utils6.URL(scheme);
|
|
474
493
|
url.search = `?${new import_utils6.URLSearchParams([
|
|
475
494
|
...url.searchParams.entries(),
|
|
476
|
-
...(0, import_utils6.objectToQueryParams)(
|
|
495
|
+
...(0, import_utils6.objectToQueryParams)(requestPayload).entries()
|
|
477
496
|
]).toString()}`;
|
|
478
497
|
return {
|
|
479
|
-
authRequestObject:
|
|
498
|
+
authRequestObject: requestPayload,
|
|
480
499
|
authRequest: url.toString(),
|
|
481
500
|
jar: void 0
|
|
482
501
|
};
|
|
@@ -562,17 +581,82 @@ function parseOpenid4vpAuthorizationRequestPayload(options) {
|
|
|
562
581
|
}
|
|
563
582
|
|
|
564
583
|
// src/authorization-request/resolve-authorization-request.ts
|
|
565
|
-
var
|
|
566
|
-
var
|
|
567
|
-
var
|
|
584
|
+
var import_oauth219 = require("@openid4vc/oauth2");
|
|
585
|
+
var import_utils13 = require("@openid4vc/utils");
|
|
586
|
+
var import_zod15 = __toESM(require("zod"));
|
|
568
587
|
|
|
569
588
|
// src/client-identifier-scheme/parse-client-identifier-scheme.ts
|
|
589
|
+
var import_oauth213 = require("@openid4vc/oauth2");
|
|
590
|
+
|
|
591
|
+
// src/version.ts
|
|
570
592
|
var import_oauth212 = require("@openid4vc/oauth2");
|
|
593
|
+
function parseAuthorizationRequestVersion(request) {
|
|
594
|
+
const requirements = [];
|
|
595
|
+
const vp_formats = request.client_metadata?.vp_formats;
|
|
596
|
+
if (isOpenid4vpAuthorizationRequestDcApi(request) && (request.response_mode === "w3c_dc_api" || request.response_mode === "w3c_dc_api.jwt")) {
|
|
597
|
+
requirements.push(["<", 23]);
|
|
598
|
+
requirements.push([">=", 21]);
|
|
599
|
+
}
|
|
600
|
+
if (isOpenid4vpAuthorizationRequestDcApi(request) && request.response_mode === "dc_api" || request.response_mode === "dc_api.jwt") {
|
|
601
|
+
requirements.push([">=", 23]);
|
|
602
|
+
}
|
|
603
|
+
if (isOpenid4vpAuthorizationRequestDcApi(request) && (request.transaction_data || request.dcql_query)) {
|
|
604
|
+
requirements.push([">=", 23]);
|
|
605
|
+
}
|
|
606
|
+
if (request.dcql_query) {
|
|
607
|
+
requirements.push([">=", 22]);
|
|
608
|
+
}
|
|
609
|
+
if (request.transaction_data) {
|
|
610
|
+
requirements.push([">=", 22]);
|
|
611
|
+
}
|
|
612
|
+
if (request.client_id_scheme) {
|
|
613
|
+
requirements.push(["<", 22]);
|
|
614
|
+
}
|
|
615
|
+
if (request.client_id) {
|
|
616
|
+
const colonIndex = request.client_id.indexOf(":");
|
|
617
|
+
const schemePart = request.client_id.substring(0, colonIndex);
|
|
618
|
+
const parsedScheme = zClientIdScheme.safeParse(schemePart);
|
|
619
|
+
if (parsedScheme.success && parsedScheme.data !== "did" && parsedScheme.data !== "https") {
|
|
620
|
+
requirements.push([">=", 22]);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
if (!request.client_id) {
|
|
624
|
+
requirements.push([">=", 21]);
|
|
625
|
+
}
|
|
626
|
+
if ("client_metadata_uri" in request) {
|
|
627
|
+
requirements.push(["<", 21]);
|
|
628
|
+
}
|
|
629
|
+
if (isOpenid4vpAuthorizationRequestDcApi(request)) {
|
|
630
|
+
requirements.push([">=", 21]);
|
|
631
|
+
}
|
|
632
|
+
if ("request_uri_method" in request || "wallet_nonce" in request) {
|
|
633
|
+
requirements.push([">=", 21]);
|
|
634
|
+
}
|
|
635
|
+
if (request.client_id_scheme === "verifier_attestation") {
|
|
636
|
+
requirements.push([">=", 20]);
|
|
637
|
+
}
|
|
638
|
+
if (request.client_id_scheme === "x509_san_dns" || request.client_id_scheme === "x509_san_uri") {
|
|
639
|
+
requirements.push([">=", 19]);
|
|
640
|
+
}
|
|
641
|
+
const lessThanVersions = requirements.filter(([operator]) => operator === "<").map(([_, version]) => version);
|
|
642
|
+
const greaterThanVersions = requirements.filter(([operator]) => operator === ">=").map(([_, version]) => version);
|
|
643
|
+
const highestPossibleVersion = lessThanVersions.length > 0 ? Math.max(Math.min(...lessThanVersions) - 1, 18) : 24;
|
|
644
|
+
const lowestRequiredVersion = greaterThanVersions.length > 0 ? Math.max(...greaterThanVersions) : 18;
|
|
645
|
+
if (lowestRequiredVersion > highestPossibleVersion) {
|
|
646
|
+
throw new import_oauth212.Oauth2ServerErrorResponseError({
|
|
647
|
+
error: import_oauth212.Oauth2ErrorCodes.InvalidRequest,
|
|
648
|
+
error_description: "Could not infer openid4vp version from the openid4vp request payload."
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
return highestPossibleVersion;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// src/client-identifier-scheme/parse-client-identifier-scheme.ts
|
|
571
655
|
function getClientId(options) {
|
|
572
656
|
if (isOpenid4vpAuthorizationRequestDcApi(options.request)) {
|
|
573
657
|
if (!options.origin) {
|
|
574
|
-
throw new
|
|
575
|
-
error:
|
|
658
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
659
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
576
660
|
error_description: "Failed to parse client identifier. 'origin' is required for requests with response_mode 'dc_api' and 'dc_api.jwt'"
|
|
577
661
|
});
|
|
578
662
|
}
|
|
@@ -581,10 +665,48 @@ function getClientId(options) {
|
|
|
581
665
|
}
|
|
582
666
|
return options.request.client_id;
|
|
583
667
|
}
|
|
668
|
+
function getLegacyClientId(options) {
|
|
669
|
+
const legacyClientIdScheme = options.request.client_id_scheme ?? "pre-registered";
|
|
670
|
+
let clientIdScheme;
|
|
671
|
+
if (legacyClientIdScheme === "entity_id") {
|
|
672
|
+
clientIdScheme = "https";
|
|
673
|
+
} else {
|
|
674
|
+
clientIdScheme = legacyClientIdScheme;
|
|
675
|
+
}
|
|
676
|
+
if (isOpenid4vpAuthorizationRequestDcApi(options.request)) {
|
|
677
|
+
if (!options.origin) {
|
|
678
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
679
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
680
|
+
error_description: "Failed to parse client identifier. 'origin' is required for requests with response_mode 'dc_api' and 'dc_api.jwt'"
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
if (!options.jar || !options.request.client_id) return `web-origin:${options.origin}`;
|
|
684
|
+
return `${clientIdScheme}:${options.request.client_id}`;
|
|
685
|
+
}
|
|
686
|
+
if (clientIdScheme === "https" || clientIdScheme === "did") {
|
|
687
|
+
return options.request.client_id;
|
|
688
|
+
}
|
|
689
|
+
if (clientIdScheme === "pre-registered") {
|
|
690
|
+
return options.request.client_id;
|
|
691
|
+
}
|
|
692
|
+
return `${clientIdScheme}:${options.request.client_id}`;
|
|
693
|
+
}
|
|
584
694
|
function parseClientIdentifier(options, parserConfig) {
|
|
585
695
|
const { request, jar } = options;
|
|
696
|
+
const version = parseAuthorizationRequestVersion(request);
|
|
697
|
+
if (version < 22) {
|
|
698
|
+
const legacyClientIdScheme = request.client_id_scheme ?? "pre-registered";
|
|
699
|
+
let clientIdSchem;
|
|
700
|
+
if (legacyClientIdScheme) {
|
|
701
|
+
if (legacyClientIdScheme === "entity_id") {
|
|
702
|
+
clientIdSchem = "https";
|
|
703
|
+
} else {
|
|
704
|
+
clientIdSchem = legacyClientIdScheme;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
586
708
|
const isDcApiRequest = isOpenid4vpAuthorizationRequestDcApi(request);
|
|
587
|
-
const clientId = getClientId(options);
|
|
709
|
+
const clientId = version < 22 ? getLegacyClientId(options) : getClientId(options);
|
|
588
710
|
const parserConfigWithDefaults = {
|
|
589
711
|
supportedSchemes: parserConfig?.supportedSchemes || Object.values(zClientIdScheme.options)
|
|
590
712
|
};
|
|
@@ -600,22 +722,22 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
600
722
|
const schemePart = clientId.substring(0, colonIndex);
|
|
601
723
|
const identifierPart = clientId.substring(colonIndex + 1);
|
|
602
724
|
if (!parserConfigWithDefaults.supportedSchemes.includes(schemePart)) {
|
|
603
|
-
throw new
|
|
604
|
-
error:
|
|
725
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
726
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
605
727
|
error_description: `Unsupported client identifier scheme. ${schemePart} is not supported.`
|
|
606
728
|
});
|
|
607
729
|
}
|
|
608
730
|
const scheme = schemePart;
|
|
609
731
|
if (scheme === "https") {
|
|
610
732
|
if (isDcApiRequest) {
|
|
611
|
-
throw new
|
|
612
|
-
error:
|
|
733
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
734
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
613
735
|
error_description: `The client identifier scheme 'https' is not supported when using the dc_api response mode.`
|
|
614
736
|
});
|
|
615
737
|
}
|
|
616
|
-
if (!clientId.startsWith("https://") && !((0,
|
|
617
|
-
throw new
|
|
618
|
-
error:
|
|
738
|
+
if (!clientId.startsWith("https://") && !((0, import_oauth213.getGlobalConfig)().allowInsecureUrls && clientId.startsWith("http://"))) {
|
|
739
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
740
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
619
741
|
error_description: "Invalid client identifier. Client identifier must start with https:// or http:// if allowInsecureUrls is true."
|
|
620
742
|
});
|
|
621
743
|
}
|
|
@@ -628,14 +750,14 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
628
750
|
}
|
|
629
751
|
if (scheme === "redirect_uri") {
|
|
630
752
|
if (jar) {
|
|
631
|
-
throw new
|
|
632
|
-
error:
|
|
753
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
754
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
633
755
|
error_description: 'Using client identifier scheme "redirect_uri" the request MUST NOT be signed.'
|
|
634
756
|
});
|
|
635
757
|
}
|
|
636
758
|
if (isOpenid4vpAuthorizationRequestDcApi(request)) {
|
|
637
|
-
throw new
|
|
638
|
-
error:
|
|
759
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
760
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
639
761
|
error_description: `The client identifier scheme 'redirect_uri' is not supported when using the dc_api response mode.`
|
|
640
762
|
});
|
|
641
763
|
}
|
|
@@ -648,26 +770,26 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
648
770
|
}
|
|
649
771
|
if (scheme === "did") {
|
|
650
772
|
if (!jar) {
|
|
651
|
-
throw new
|
|
652
|
-
error:
|
|
773
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
774
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
653
775
|
error_description: 'Using client identifier scheme "did" requires a signed JAR request.'
|
|
654
776
|
});
|
|
655
777
|
}
|
|
656
778
|
if (!clientId.startsWith("did:")) {
|
|
657
|
-
throw new
|
|
658
|
-
error:
|
|
779
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
780
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
659
781
|
error_description: "Invalid client identifier. Client identifier must start with 'did:'"
|
|
660
782
|
});
|
|
661
783
|
}
|
|
662
784
|
if (!jar.signer.publicJwk.kid) {
|
|
663
|
-
throw new
|
|
664
|
-
error:
|
|
785
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
786
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
665
787
|
error_description: `Missing required 'kid' for client identifier scheme: did`
|
|
666
788
|
});
|
|
667
789
|
}
|
|
668
790
|
if (!jar.signer.publicJwk.kid?.startsWith(clientId)) {
|
|
669
|
-
throw new
|
|
670
|
-
error:
|
|
791
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
792
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
671
793
|
error_description: 'With client identifier scheme "did" the JAR request must be signed by the same DID as the client identifier.'
|
|
672
794
|
});
|
|
673
795
|
}
|
|
@@ -680,22 +802,22 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
680
802
|
}
|
|
681
803
|
if (scheme === "x509_san_dns" || scheme === "x509_san_uri") {
|
|
682
804
|
if (!jar) {
|
|
683
|
-
throw new
|
|
684
|
-
error:
|
|
805
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
806
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
685
807
|
error_description: 'Using client identifier scheme "x509_san_dns" or "x509_san_uri" requires a signed JAR request.'
|
|
686
808
|
});
|
|
687
809
|
}
|
|
688
810
|
if (jar.signer.method !== "x5c") {
|
|
689
|
-
throw new
|
|
690
|
-
error:
|
|
811
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
812
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
691
813
|
error_description: "Something went wrong. The JWT signer method is not x5c but the client identifier scheme is x509_san_dns."
|
|
692
814
|
});
|
|
693
815
|
}
|
|
694
816
|
if (scheme === "x509_san_dns") {
|
|
695
817
|
if (!options.callbacks.getX509CertificateMetadata) {
|
|
696
|
-
throw new
|
|
818
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError(
|
|
697
819
|
{
|
|
698
|
-
error:
|
|
820
|
+
error: import_oauth213.Oauth2ErrorCodes.ServerError
|
|
699
821
|
},
|
|
700
822
|
{
|
|
701
823
|
internalMessage: "Missing required 'getX509CertificateMetadata' callback for verification of 'x509_san_dns' client id scheme"
|
|
@@ -704,25 +826,25 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
704
826
|
}
|
|
705
827
|
const { sanDnsNames } = options.callbacks.getX509CertificateMetadata(jar.signer.x5c[0]);
|
|
706
828
|
if (!sanDnsNames.includes(identifierPart)) {
|
|
707
|
-
throw new
|
|
708
|
-
error:
|
|
709
|
-
error_description:
|
|
829
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
830
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
831
|
+
error_description: `Invalid client identifier. One of the leaf certificates san dns names [${sanDnsNames.join(", ")}] must match the client identifier '${identifierPart}'. `
|
|
710
832
|
});
|
|
711
833
|
}
|
|
712
834
|
if (!isOpenid4vpAuthorizationRequestDcApi(request)) {
|
|
713
835
|
const uri = request.redirect_uri ?? request.response_uri;
|
|
714
836
|
if (!uri || getDomainFromUrl(uri) !== identifierPart) {
|
|
715
|
-
throw new
|
|
716
|
-
error:
|
|
837
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
838
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
717
839
|
error_description: "Invalid client identifier. The fully qualified domain name of the redirect_uri value MUST match the Client Identifier without the prefix x509_san_dns."
|
|
718
840
|
});
|
|
719
841
|
}
|
|
720
842
|
}
|
|
721
843
|
} else if (scheme === "x509_san_uri") {
|
|
722
844
|
if (!options.callbacks.getX509CertificateMetadata) {
|
|
723
|
-
throw new
|
|
845
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError(
|
|
724
846
|
{
|
|
725
|
-
error:
|
|
847
|
+
error: import_oauth213.Oauth2ErrorCodes.ServerError
|
|
726
848
|
},
|
|
727
849
|
{
|
|
728
850
|
internalMessage: "Missing required 'getX509CertificateMetadata' callback for verification of 'x509_san_uri' client id scheme"
|
|
@@ -731,16 +853,16 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
731
853
|
}
|
|
732
854
|
const { sanUriNames } = options.callbacks.getX509CertificateMetadata(jar.signer.x5c[0]);
|
|
733
855
|
if (!sanUriNames.includes(identifierPart)) {
|
|
734
|
-
throw new
|
|
735
|
-
error:
|
|
736
|
-
error_description:
|
|
856
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
857
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
858
|
+
error_description: `Invalid client identifier. One of the leaf certificates san uri names [${sanUriNames.join(", ")}] must match the client identifier '${identifierPart}'.`
|
|
737
859
|
});
|
|
738
860
|
}
|
|
739
861
|
if (!isOpenid4vpAuthorizationRequestDcApi(request)) {
|
|
740
862
|
const uri = request.redirect_uri || request.response_uri;
|
|
741
863
|
if (!uri || uri !== identifierPart) {
|
|
742
|
-
throw new
|
|
743
|
-
error:
|
|
864
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
865
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
744
866
|
error_description: "The redirect_uri value MUST match the Client Identifier without the prefix x509_san_uri"
|
|
745
867
|
});
|
|
746
868
|
}
|
|
@@ -763,8 +885,8 @@ function parseClientIdentifier(options, parserConfig) {
|
|
|
763
885
|
}
|
|
764
886
|
if (scheme === "verifier_attestation") {
|
|
765
887
|
if (!jar) {
|
|
766
|
-
throw new
|
|
767
|
-
error:
|
|
888
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
889
|
+
error: import_oauth213.Oauth2ErrorCodes.InvalidRequest,
|
|
768
890
|
error_description: 'Using client identifier scheme "verifier_attestation" requires a signed JAR request.'
|
|
769
891
|
});
|
|
770
892
|
}
|
|
@@ -781,57 +903,97 @@ function getDomainFromUrl(url) {
|
|
|
781
903
|
const domain = url.split("://")[1].split(regex)[0];
|
|
782
904
|
return domain;
|
|
783
905
|
} catch (error) {
|
|
784
|
-
throw new
|
|
785
|
-
error:
|
|
906
|
+
throw new import_oauth213.Oauth2ServerErrorResponseError({
|
|
907
|
+
error: import_oauth213.Oauth2ErrorCodes.ServerError,
|
|
786
908
|
error_description: `Url '${url}' is not a valid URL`
|
|
787
909
|
});
|
|
788
910
|
}
|
|
789
911
|
}
|
|
790
912
|
|
|
913
|
+
// src/fetch-client-metadata.ts
|
|
914
|
+
var import_oauth214 = require("@openid4vc/oauth2");
|
|
915
|
+
var import_utils10 = require("@openid4vc/utils");
|
|
916
|
+
|
|
917
|
+
// src/models/z-wallet-metadata.ts
|
|
918
|
+
var import_zod11 = require("zod");
|
|
919
|
+
var zWalletMetadata = import_zod11.z.object({
|
|
920
|
+
presentation_definition_uri_supported: import_zod11.z.optional(import_zod11.z.boolean()),
|
|
921
|
+
vp_formats_supported: zVpFormatsSupported,
|
|
922
|
+
client_id_schemes_supported: import_zod11.z.optional(import_zod11.z.array(zClientIdScheme)),
|
|
923
|
+
request_object_signing_alg_values_supported: import_zod11.z.optional(import_zod11.z.array(import_zod11.z.string())),
|
|
924
|
+
authorization_encryption_alg_values_supported: import_zod11.z.optional(import_zod11.z.array(import_zod11.z.string())),
|
|
925
|
+
authorization_encryption_enc_values_supported: import_zod11.z.optional(import_zod11.z.array(import_zod11.z.string()))
|
|
926
|
+
});
|
|
927
|
+
|
|
928
|
+
// src/fetch-client-metadata.ts
|
|
929
|
+
async function fetchClientMetadata(options) {
|
|
930
|
+
const { fetch, clientMetadataUri } = options;
|
|
931
|
+
const fetcher = (0, import_utils10.createZodFetcher)(fetch);
|
|
932
|
+
const { result, response } = await fetcher(zWalletMetadata, import_utils10.ContentType.Json, clientMetadataUri, {
|
|
933
|
+
method: "GET",
|
|
934
|
+
headers: {
|
|
935
|
+
Accept: import_utils10.ContentType.Json
|
|
936
|
+
}
|
|
937
|
+
});
|
|
938
|
+
if (!response.ok) {
|
|
939
|
+
throw new import_oauth214.Oauth2ServerErrorResponseError({
|
|
940
|
+
error_description: `Fetching client metadata from '${clientMetadataUri}' failed with status code '${response.status}'.`,
|
|
941
|
+
error: import_oauth214.Oauth2ErrorCodes.InvalidRequestUri
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
if (!result || !result.success) {
|
|
945
|
+
throw new import_oauth214.Oauth2ServerErrorResponseError({
|
|
946
|
+
error_description: `Parsing client metadata from '${clientMetadataUri}' failed.`,
|
|
947
|
+
error: import_oauth214.Oauth2ErrorCodes.InvalidRequestObject
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
return result.data;
|
|
951
|
+
}
|
|
952
|
+
|
|
791
953
|
// src/jar/handle-jar-request/verify-jar-request.ts
|
|
792
|
-
var
|
|
954
|
+
var import_oauth217 = require("@openid4vc/oauth2");
|
|
793
955
|
|
|
794
956
|
// src/jar/jar-request-object/fetch-jar-request-object.ts
|
|
795
|
-
var
|
|
796
|
-
var
|
|
797
|
-
var
|
|
957
|
+
var import_oauth215 = require("@openid4vc/oauth2");
|
|
958
|
+
var import_utils11 = require("@openid4vc/utils");
|
|
959
|
+
var import_zod12 = require("zod");
|
|
798
960
|
async function fetchJarRequestObject(options) {
|
|
799
961
|
const { requestUri, clientIdentifierScheme, method, wallet, fetch } = options;
|
|
800
|
-
const fetcher = (0,
|
|
962
|
+
const fetcher = (0, import_utils11.createZodFetcher)(fetch);
|
|
801
963
|
let requestBody = wallet.metadata ? { wallet_metadata: wallet.metadata, wallet_nonce: wallet.nonce } : void 0;
|
|
802
964
|
if (requestBody?.wallet_metadata?.request_object_signing_alg_values_supported && clientIdentifierScheme === "redirect_uri") {
|
|
803
965
|
const { request_object_signing_alg_values_supported, ...rest } = requestBody.wallet_metadata;
|
|
804
966
|
requestBody = { ...requestBody, wallet_metadata: { ...rest } };
|
|
805
967
|
}
|
|
806
|
-
const { result, response } = await fetcher(
|
|
968
|
+
const { result, response } = await fetcher(import_zod12.z.string(), import_utils11.ContentType.OAuthRequestObjectJwt, requestUri, {
|
|
807
969
|
method,
|
|
808
970
|
headers: {
|
|
809
|
-
Accept: `${
|
|
810
|
-
"Content-Type":
|
|
971
|
+
Accept: `${import_utils11.ContentType.OAuthRequestObjectJwt}, ${import_utils11.ContentType.Jwt};q=0.9`,
|
|
972
|
+
"Content-Type": import_utils11.ContentType.XWwwFormUrlencoded
|
|
811
973
|
},
|
|
812
|
-
body: method === "POST" ? (0,
|
|
974
|
+
body: method === "POST" ? (0, import_utils11.objectToQueryParams)(wallet.metadata ?? {}) : void 0
|
|
813
975
|
});
|
|
814
976
|
if (!response.ok) {
|
|
815
|
-
throw new
|
|
977
|
+
throw new import_oauth215.Oauth2ServerErrorResponseError({
|
|
816
978
|
error_description: `Fetching request_object from request_uri '${requestUri}' failed with status code '${response.status}'.`,
|
|
817
|
-
error:
|
|
979
|
+
error: import_oauth215.Oauth2ErrorCodes.InvalidRequestUri
|
|
818
980
|
});
|
|
819
981
|
}
|
|
820
982
|
if (!result || !result.success) {
|
|
821
|
-
throw new
|
|
983
|
+
throw new import_oauth215.Oauth2ServerErrorResponseError({
|
|
822
984
|
error_description: `Parsing request_object from request_uri '${requestUri}' failed.`,
|
|
823
|
-
error:
|
|
985
|
+
error: import_oauth215.Oauth2ErrorCodes.InvalidRequestObject
|
|
824
986
|
});
|
|
825
987
|
}
|
|
826
988
|
return result.data;
|
|
827
989
|
}
|
|
828
990
|
|
|
829
991
|
// src/jar/jar-request-object/z-jar-request-object.ts
|
|
830
|
-
var
|
|
831
|
-
var
|
|
832
|
-
var zJarRequestObjectPayload =
|
|
833
|
-
...
|
|
834
|
-
client_id:
|
|
992
|
+
var import_oauth216 = require("@openid4vc/oauth2");
|
|
993
|
+
var import_zod13 = require("zod");
|
|
994
|
+
var zJarRequestObjectPayload = import_zod13.z.object({
|
|
995
|
+
...import_oauth216.zJwtPayload.shape,
|
|
996
|
+
client_id: import_zod13.z.string()
|
|
835
997
|
}).passthrough();
|
|
836
998
|
|
|
837
999
|
// src/jar/handle-jar-request/verify-jar-request.ts
|
|
@@ -842,8 +1004,8 @@ async function verifyJarRequest(options) {
|
|
|
842
1004
|
const clientIdentifierScheme = jarRequestParams.client_id ? zClientIdScheme.parse(jarRequestParams.client_id.split(":")[0]) : "web-origin";
|
|
843
1005
|
const method = jarRequestParams.request_uri_method ?? "GET";
|
|
844
1006
|
if (method !== "GET" && method !== "POST") {
|
|
845
|
-
throw new
|
|
846
|
-
error:
|
|
1007
|
+
throw new import_oauth217.Oauth2ServerErrorResponseError({
|
|
1008
|
+
error: import_oauth217.Oauth2ErrorCodes.InvalidRequestUriMethod,
|
|
847
1009
|
error_description: "Invalid request_uri_method. Must be GET or POST."
|
|
848
1010
|
});
|
|
849
1011
|
}
|
|
@@ -853,12 +1015,12 @@ async function verifyJarRequest(options) {
|
|
|
853
1015
|
method,
|
|
854
1016
|
wallet
|
|
855
1017
|
});
|
|
856
|
-
const requestObjectIsEncrypted =
|
|
1018
|
+
const requestObjectIsEncrypted = import_oauth217.zCompactJwe.safeParse(requestObject).success;
|
|
857
1019
|
const { decryptionJwk, payload: decryptedRequestObject } = requestObjectIsEncrypted ? await decryptJarRequest({ jwe: requestObject, callbacks }) : { payload: requestObject, decryptionJwk: void 0 };
|
|
858
|
-
const requestIsSigned =
|
|
1020
|
+
const requestIsSigned = import_oauth217.zCompactJwt.safeParse(decryptedRequestObject).success;
|
|
859
1021
|
if (!requestIsSigned) {
|
|
860
|
-
throw new
|
|
861
|
-
error:
|
|
1022
|
+
throw new import_oauth217.Oauth2ServerErrorResponseError({
|
|
1023
|
+
error: import_oauth217.Oauth2ErrorCodes.InvalidRequestObject,
|
|
862
1024
|
error_description: "Jar Request Object is not a valid JWS."
|
|
863
1025
|
});
|
|
864
1026
|
}
|
|
@@ -867,14 +1029,14 @@ async function verifyJarRequest(options) {
|
|
|
867
1029
|
callbacks
|
|
868
1030
|
});
|
|
869
1031
|
if (!authRequestParams.client_id) {
|
|
870
|
-
throw new
|
|
871
|
-
error:
|
|
1032
|
+
throw new import_oauth217.Oauth2ServerErrorResponseError({
|
|
1033
|
+
error: import_oauth217.Oauth2ErrorCodes.InvalidRequestObject,
|
|
872
1034
|
error_description: 'Jar Request Object is missing the required "client_id" field.'
|
|
873
1035
|
});
|
|
874
1036
|
}
|
|
875
1037
|
if (jarRequestParams.client_id !== authRequestParams.client_id) {
|
|
876
|
-
throw new
|
|
877
|
-
error:
|
|
1038
|
+
throw new import_oauth217.Oauth2ServerErrorResponseError({
|
|
1039
|
+
error: import_oauth217.Oauth2ErrorCodes.InvalidRequest,
|
|
878
1040
|
error_description: "client_id does not match the request object client_id."
|
|
879
1041
|
});
|
|
880
1042
|
}
|
|
@@ -887,16 +1049,16 @@ async function verifyJarRequest(options) {
|
|
|
887
1049
|
}
|
|
888
1050
|
async function decryptJarRequest(options) {
|
|
889
1051
|
const { jwe, callbacks } = options;
|
|
890
|
-
const { header } = (0,
|
|
1052
|
+
const { header } = (0, import_oauth217.decodeJwt)({ jwt: jwe });
|
|
891
1053
|
if (!header.kid) {
|
|
892
|
-
throw new
|
|
893
|
-
error:
|
|
1054
|
+
throw new import_oauth217.Oauth2ServerErrorResponseError({
|
|
1055
|
+
error: import_oauth217.Oauth2ErrorCodes.InvalidRequestObject,
|
|
894
1056
|
error_description: 'Jar JWE is missing the protected header field "kid".'
|
|
895
1057
|
});
|
|
896
1058
|
}
|
|
897
1059
|
const decryptionResult = await callbacks.decryptJwe(jwe);
|
|
898
1060
|
if (!decryptionResult.decrypted) {
|
|
899
|
-
throw new
|
|
1061
|
+
throw new import_oauth217.Oauth2ServerErrorResponseError({
|
|
900
1062
|
error: "invalid_request_object",
|
|
901
1063
|
error_description: "Failed to decrypt jar request object."
|
|
902
1064
|
});
|
|
@@ -905,39 +1067,46 @@ async function decryptJarRequest(options) {
|
|
|
905
1067
|
}
|
|
906
1068
|
async function verifyJarRequestObject(options) {
|
|
907
1069
|
const { decryptedRequestObject, callbacks } = options;
|
|
908
|
-
const jwt = (0,
|
|
909
|
-
const jwtSigner = (0,
|
|
910
|
-
const { signer } = await (0,
|
|
1070
|
+
const jwt = (0, import_oauth217.decodeJwt)({ jwt: decryptedRequestObject, payloadSchema: zJarRequestObjectPayload });
|
|
1071
|
+
const jwtSigner = (0, import_oauth217.jwtSignerFromJwt)(jwt);
|
|
1072
|
+
const { signer } = await (0, import_oauth217.verifyJwt)({
|
|
911
1073
|
verifyJwtCallback: callbacks.verifyJwt,
|
|
912
1074
|
compact: decryptedRequestObject,
|
|
913
1075
|
header: jwt.header,
|
|
914
1076
|
payload: jwt.payload,
|
|
915
1077
|
signer: jwtSigner
|
|
916
1078
|
});
|
|
1079
|
+
const version = parseAuthorizationRequestVersion(jwt.payload);
|
|
1080
|
+
if (jwt.header.typ !== "oauth-authz-req+jwt" && version >= 24) {
|
|
1081
|
+
throw new import_oauth217.Oauth2ServerErrorResponseError({
|
|
1082
|
+
error: import_oauth217.Oauth2ErrorCodes.InvalidRequestObject,
|
|
1083
|
+
error_description: `Invalid Jar Request Object typ header. Expected "oauth-authz-req+jwt", received "${jwt.header.typ}".`
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
917
1086
|
return { authRequestParams: jwt.payload, signer };
|
|
918
1087
|
}
|
|
919
1088
|
|
|
920
1089
|
// src/transaction-data/parse-transaction-data.ts
|
|
921
|
-
var
|
|
922
|
-
var
|
|
1090
|
+
var import_oauth218 = require("@openid4vc/oauth2");
|
|
1091
|
+
var import_utils12 = require("@openid4vc/utils");
|
|
923
1092
|
|
|
924
1093
|
// src/transaction-data/z-transaction-data.ts
|
|
925
|
-
var
|
|
926
|
-
var zTransactionEntry =
|
|
927
|
-
type:
|
|
928
|
-
credential_ids:
|
|
929
|
-
transaction_data_hashes_alg:
|
|
1094
|
+
var import_zod14 = require("zod");
|
|
1095
|
+
var zTransactionEntry = import_zod14.z.object({
|
|
1096
|
+
type: import_zod14.z.string(),
|
|
1097
|
+
credential_ids: import_zod14.z.array(import_zod14.z.string()).min(1),
|
|
1098
|
+
transaction_data_hashes_alg: import_zod14.z.array(import_zod14.z.string()).optional()
|
|
930
1099
|
});
|
|
931
|
-
var zTransactionData =
|
|
1100
|
+
var zTransactionData = import_zod14.z.array(zTransactionEntry);
|
|
932
1101
|
|
|
933
1102
|
// src/transaction-data/parse-transaction-data.ts
|
|
934
1103
|
function parseTransactionData(options) {
|
|
935
1104
|
const { transactionData } = options;
|
|
936
|
-
const decoded = transactionData.map((tdEntry) => (0,
|
|
1105
|
+
const decoded = transactionData.map((tdEntry) => (0, import_utils12.parseIfJson)((0, import_utils12.encodeToUtf8String)((0, import_utils12.decodeBase64)(tdEntry))));
|
|
937
1106
|
const parsedResult = zTransactionData.safeParse(decoded);
|
|
938
1107
|
if (!parsedResult.success) {
|
|
939
|
-
throw new
|
|
940
|
-
error:
|
|
1108
|
+
throw new import_oauth218.Oauth2ServerErrorResponseError({
|
|
1109
|
+
error: import_oauth218.Oauth2ErrorCodes.InvalidTransactionData,
|
|
941
1110
|
error_description: "Failed to parse transaction data."
|
|
942
1111
|
});
|
|
943
1112
|
}
|
|
@@ -946,18 +1115,18 @@ function parseTransactionData(options) {
|
|
|
946
1115
|
|
|
947
1116
|
// src/authorization-request/resolve-authorization-request.ts
|
|
948
1117
|
async function resolveOpenid4vpAuthorizationRequest(options) {
|
|
949
|
-
const {
|
|
1118
|
+
const { requestPayload, wallet, callbacks, origin, omitOriginValidation } = options;
|
|
950
1119
|
let authRequestPayload;
|
|
951
|
-
const parsed = (0,
|
|
952
|
-
|
|
953
|
-
|
|
1120
|
+
const parsed = (0, import_utils13.parseWithErrorHandling)(
|
|
1121
|
+
import_zod15.default.union([zOpenid4vpAuthorizationRequestDcApi, zOpenid4vpAuthorizationRequest, zJarAuthRequest]),
|
|
1122
|
+
requestPayload,
|
|
954
1123
|
"Invalid authorization request. Could not parse openid4vp authorization request as openid4vp or jar auth request."
|
|
955
1124
|
);
|
|
956
1125
|
let jar;
|
|
957
1126
|
if (isJarAuthRequest(parsed)) {
|
|
958
1127
|
jar = await verifyJarRequest({ jarRequestParams: parsed, callbacks, wallet });
|
|
959
|
-
const parsedJarAuthRequestPayload = (0,
|
|
960
|
-
|
|
1128
|
+
const parsedJarAuthRequestPayload = (0, import_utils13.parseWithErrorHandling)(
|
|
1129
|
+
import_zod15.default.union([zOpenid4vpAuthorizationRequestDcApi, zOpenid4vpAuthorizationRequest]),
|
|
961
1130
|
jar.authRequestParams,
|
|
962
1131
|
"Invalid authorization request. Could not parse jar request payload as openid4vp auth request."
|
|
963
1132
|
);
|
|
@@ -977,13 +1146,22 @@ async function resolveOpenid4vpAuthorizationRequest(options) {
|
|
|
977
1146
|
omitOriginValidation
|
|
978
1147
|
});
|
|
979
1148
|
}
|
|
980
|
-
|
|
1149
|
+
let clientMetadata;
|
|
1150
|
+
if (!isOpenid4vpAuthorizationRequestDcApi(authRequestPayload) && authRequestPayload.client_metadata_uri) {
|
|
1151
|
+
clientMetadata = await fetchClientMetadata({ clientMetadataUri: authRequestPayload.client_metadata_uri });
|
|
1152
|
+
}
|
|
1153
|
+
const clientMeta = parseClientIdentifier({
|
|
1154
|
+
request: { ...authRequestPayload, client_metadata: clientMetadata ?? authRequestPayload.client_metadata },
|
|
1155
|
+
jar,
|
|
1156
|
+
callbacks,
|
|
1157
|
+
origin
|
|
1158
|
+
});
|
|
981
1159
|
let pex;
|
|
982
1160
|
let dcql;
|
|
983
1161
|
if (authRequestPayload.presentation_definition || authRequestPayload.presentation_definition_uri) {
|
|
984
1162
|
if (authRequestPayload.presentation_definition_uri) {
|
|
985
|
-
throw new
|
|
986
|
-
error:
|
|
1163
|
+
throw new import_oauth219.Oauth2ServerErrorResponseError({
|
|
1164
|
+
error: import_oauth219.Oauth2ErrorCodes.InvalidRequest,
|
|
987
1165
|
error_description: "Cannot fetch presentation definition from URI. Not supported."
|
|
988
1166
|
});
|
|
989
1167
|
}
|
|
@@ -998,7 +1176,7 @@ async function resolveOpenid4vpAuthorizationRequest(options) {
|
|
|
998
1176
|
const transactionData = authRequestPayload.transaction_data ? parseTransactionData({ transactionData: authRequestPayload.transaction_data }) : void 0;
|
|
999
1177
|
return {
|
|
1000
1178
|
transactionData,
|
|
1001
|
-
|
|
1179
|
+
requestPayload: authRequestPayload,
|
|
1002
1180
|
jar,
|
|
1003
1181
|
client: { ...clientMeta },
|
|
1004
1182
|
pex,
|
|
@@ -1021,8 +1199,8 @@ function validateOpenId4vpPayload(options) {
|
|
|
1021
1199
|
}
|
|
1022
1200
|
|
|
1023
1201
|
// src/authorization-response/create-authorization-response.ts
|
|
1024
|
-
var
|
|
1025
|
-
var
|
|
1202
|
+
var import_oauth222 = require("@openid4vc/oauth2");
|
|
1203
|
+
var import_utils14 = require("@openid4vc/utils");
|
|
1026
1204
|
|
|
1027
1205
|
// ../utils/src/date.ts
|
|
1028
1206
|
function addSecondsToDate(date, seconds) {
|
|
@@ -1030,7 +1208,7 @@ function addSecondsToDate(date, seconds) {
|
|
|
1030
1208
|
}
|
|
1031
1209
|
|
|
1032
1210
|
// src/jarm/jarm-auth-response-create.ts
|
|
1033
|
-
var
|
|
1211
|
+
var import_oauth220 = require("@openid4vc/oauth2");
|
|
1034
1212
|
async function createJarmAuthResponse(options) {
|
|
1035
1213
|
const { jarmAuthResponse, jweEncryptor, jwtSigner, callbacks } = options;
|
|
1036
1214
|
if (!jwtSigner && jweEncryptor) {
|
|
@@ -1039,16 +1217,16 @@ async function createJarmAuthResponse(options) {
|
|
|
1039
1217
|
}
|
|
1040
1218
|
if (jwtSigner && !jweEncryptor) {
|
|
1041
1219
|
const signed2 = await callbacks.signJwt(jwtSigner, {
|
|
1042
|
-
header: (0,
|
|
1220
|
+
header: (0, import_oauth220.jwtHeaderFromJwtSigner)(jwtSigner),
|
|
1043
1221
|
payload: jarmAuthResponse
|
|
1044
1222
|
});
|
|
1045
1223
|
return { jarmAuthResponseJwt: signed2.jwt };
|
|
1046
1224
|
}
|
|
1047
1225
|
if (!jwtSigner || !jweEncryptor) {
|
|
1048
|
-
throw new
|
|
1226
|
+
throw new import_oauth220.Oauth2Error("JWT signer and/or encryptor are required to create a JARM auth response.");
|
|
1049
1227
|
}
|
|
1050
1228
|
const signed = await callbacks.signJwt(jwtSigner, {
|
|
1051
|
-
header: (0,
|
|
1229
|
+
header: (0, import_oauth220.jwtHeaderFromJwtSigner)(jwtSigner),
|
|
1052
1230
|
payload: jarmAuthResponse
|
|
1053
1231
|
});
|
|
1054
1232
|
const encrypted = await callbacks.encryptJwe(jweEncryptor, signed.jwt);
|
|
@@ -1066,7 +1244,7 @@ function extractJwksFromClientMetadata(clientMetadata) {
|
|
|
1066
1244
|
}
|
|
1067
1245
|
|
|
1068
1246
|
// src/jarm/jarm-response-mode.ts
|
|
1069
|
-
var
|
|
1247
|
+
var import_zod16 = require("zod");
|
|
1070
1248
|
var jarmResponseMode = [
|
|
1071
1249
|
"jwt",
|
|
1072
1250
|
"query.jwt",
|
|
@@ -1075,18 +1253,18 @@ var jarmResponseMode = [
|
|
|
1075
1253
|
"direct_post.jwt",
|
|
1076
1254
|
"dc_api.jwt"
|
|
1077
1255
|
];
|
|
1078
|
-
var zJarmResponseMode =
|
|
1256
|
+
var zJarmResponseMode = import_zod16.z.enum(jarmResponseMode);
|
|
1079
1257
|
var isJarmResponseMode = (responseMode) => {
|
|
1080
1258
|
return jarmResponseMode.includes(responseMode);
|
|
1081
1259
|
};
|
|
1082
1260
|
|
|
1083
1261
|
// src/jarm/metadata/jarm-assert-metadata-supported.ts
|
|
1084
|
-
var
|
|
1262
|
+
var import_oauth221 = require("@openid4vc/oauth2");
|
|
1085
1263
|
function assertValueSupported(options) {
|
|
1086
1264
|
const { errorMessage, supported, actual } = options;
|
|
1087
1265
|
const intersection = supported.find((value) => value === actual);
|
|
1088
1266
|
if (!intersection) {
|
|
1089
|
-
throw new
|
|
1267
|
+
throw new import_oauth221.Oauth2Error(errorMessage);
|
|
1090
1268
|
}
|
|
1091
1269
|
return intersection;
|
|
1092
1270
|
}
|
|
@@ -1121,77 +1299,77 @@ function jarmAssertMetadataSupported(options) {
|
|
|
1121
1299
|
|
|
1122
1300
|
// src/authorization-response/create-authorization-response.ts
|
|
1123
1301
|
async function createOpenid4vpAuthorizationResponse(options) {
|
|
1124
|
-
const {
|
|
1125
|
-
const
|
|
1126
|
-
...
|
|
1127
|
-
..."state" in
|
|
1302
|
+
const { requestPayload, jarm, callbacks } = options;
|
|
1303
|
+
const responsePayload = {
|
|
1304
|
+
...options.responsePayload,
|
|
1305
|
+
..."state" in requestPayload && { state: requestPayload.state }
|
|
1128
1306
|
};
|
|
1129
|
-
if (
|
|
1130
|
-
throw new
|
|
1131
|
-
`Missing jarm options for creating Jarm response with response mode '${
|
|
1307
|
+
if (requestPayload.response_mode && isJarmResponseMode(requestPayload.response_mode) && !jarm) {
|
|
1308
|
+
throw new import_oauth222.Oauth2Error(
|
|
1309
|
+
`Missing jarm options for creating Jarm response with response mode '${requestPayload.response_mode}'`
|
|
1132
1310
|
);
|
|
1133
1311
|
}
|
|
1134
1312
|
if (!jarm) {
|
|
1135
1313
|
return {
|
|
1136
|
-
|
|
1314
|
+
responsePayload
|
|
1137
1315
|
};
|
|
1138
1316
|
}
|
|
1139
|
-
if (!
|
|
1140
|
-
throw new
|
|
1317
|
+
if (!requestPayload.client_metadata) {
|
|
1318
|
+
throw new import_oauth222.Oauth2Error("Missing client metadata in the request params to assert Jarm metadata support.");
|
|
1141
1319
|
}
|
|
1142
|
-
if (!
|
|
1143
|
-
throw new
|
|
1144
|
-
error:
|
|
1320
|
+
if (!requestPayload.client_metadata.jwks) {
|
|
1321
|
+
throw new import_oauth222.Oauth2ServerErrorResponseError({
|
|
1322
|
+
error: import_oauth222.Oauth2ErrorCodes.InvalidRequest,
|
|
1145
1323
|
error_description: "Missing JWKS in client metadata. Cannot extract encryption JWK."
|
|
1146
1324
|
});
|
|
1147
1325
|
}
|
|
1148
1326
|
const supportedJarmMetadata = jarmAssertMetadataSupported({
|
|
1149
|
-
clientMetadata:
|
|
1327
|
+
clientMetadata: requestPayload.client_metadata,
|
|
1150
1328
|
serverMetadata: jarm.serverMetadata
|
|
1151
1329
|
});
|
|
1152
1330
|
const clientMetaJwks = extractJwksFromClientMetadata({
|
|
1153
|
-
...
|
|
1154
|
-
jwks:
|
|
1331
|
+
...requestPayload.client_metadata,
|
|
1332
|
+
jwks: requestPayload.client_metadata.jwks
|
|
1155
1333
|
});
|
|
1156
1334
|
if (!clientMetaJwks?.encJwk) {
|
|
1157
|
-
throw new
|
|
1158
|
-
error:
|
|
1335
|
+
throw new import_oauth222.Oauth2ServerErrorResponseError({
|
|
1336
|
+
error: import_oauth222.Oauth2ErrorCodes.InvalidRequest,
|
|
1159
1337
|
error_description: "Could not extract encryption JWK from client metadata. Failed to create JARM response."
|
|
1160
1338
|
});
|
|
1161
1339
|
}
|
|
1162
1340
|
let additionalJwtPayload;
|
|
1163
1341
|
if (jarm?.jwtSigner) {
|
|
1164
1342
|
if (!jarm.authorizationServer) {
|
|
1165
|
-
throw new
|
|
1166
|
-
error:
|
|
1343
|
+
throw new import_oauth222.Oauth2ServerErrorResponseError({
|
|
1344
|
+
error: import_oauth222.Oauth2ErrorCodes.InvalidRequest,
|
|
1167
1345
|
error_description: "Missing required iss in JARM configuration for creating OpenID4VP authorization response."
|
|
1168
1346
|
});
|
|
1169
1347
|
}
|
|
1170
1348
|
if (!jarm.audience) {
|
|
1171
|
-
throw new
|
|
1172
|
-
error:
|
|
1349
|
+
throw new import_oauth222.Oauth2ServerErrorResponseError({
|
|
1350
|
+
error: import_oauth222.Oauth2ErrorCodes.InvalidRequest,
|
|
1173
1351
|
error_description: "Missing required aud in JARM configuration for creating OpenID4VP authorization response."
|
|
1174
1352
|
});
|
|
1175
1353
|
}
|
|
1176
1354
|
additionalJwtPayload = {
|
|
1177
1355
|
iss: jarm.authorizationServer,
|
|
1178
1356
|
aud: jarm.audience,
|
|
1179
|
-
exp: jarm.expiresInSeconds ?? (0,
|
|
1357
|
+
exp: jarm.expiresInSeconds ?? (0, import_utils14.dateToSeconds)(addSecondsToDate(/* @__PURE__ */ new Date(), 60 * 10))
|
|
1180
1358
|
// default: 10 minutes
|
|
1181
1359
|
};
|
|
1182
1360
|
}
|
|
1183
|
-
const
|
|
1184
|
-
...
|
|
1361
|
+
const jarmResponsePayload = {
|
|
1362
|
+
...responsePayload,
|
|
1185
1363
|
...additionalJwtPayload
|
|
1186
1364
|
};
|
|
1187
1365
|
const result = await createJarmAuthResponse({
|
|
1188
|
-
jarmAuthResponse:
|
|
1366
|
+
jarmAuthResponse: jarmResponsePayload,
|
|
1189
1367
|
jwtSigner: jarm?.jwtSigner,
|
|
1190
1368
|
jweEncryptor: jarm?.encryption && (supportedJarmMetadata.type === "encrypt" || supportedJarmMetadata.type === "sign_encrypt") ? {
|
|
1191
1369
|
method: "jwk",
|
|
1192
1370
|
publicJwk: clientMetaJwks.encJwk,
|
|
1193
1371
|
apu: jarm.encryption?.nonce,
|
|
1194
|
-
apv:
|
|
1372
|
+
apv: requestPayload.nonce,
|
|
1195
1373
|
alg: supportedJarmMetadata.client_metadata.authorization_encrypted_response_alg,
|
|
1196
1374
|
enc: supportedJarmMetadata.client_metadata.authorization_encrypted_response_enc
|
|
1197
1375
|
} : void 0,
|
|
@@ -1201,32 +1379,32 @@ async function createOpenid4vpAuthorizationResponse(options) {
|
|
|
1201
1379
|
}
|
|
1202
1380
|
});
|
|
1203
1381
|
return {
|
|
1204
|
-
|
|
1382
|
+
responsePayload: jarmResponsePayload,
|
|
1205
1383
|
jarm: { responseJwt: result.jarmAuthResponseJwt }
|
|
1206
1384
|
};
|
|
1207
1385
|
}
|
|
1208
1386
|
|
|
1209
1387
|
// src/authorization-response/submit-authorization-response.ts
|
|
1210
|
-
var
|
|
1211
|
-
var import_utils15 = require("@openid4vc/utils");
|
|
1388
|
+
var import_oauth224 = require("@openid4vc/oauth2");
|
|
1212
1389
|
var import_utils16 = require("@openid4vc/utils");
|
|
1390
|
+
var import_utils17 = require("@openid4vc/utils");
|
|
1213
1391
|
|
|
1214
1392
|
// src/jarm/jarm-auth-response-send.ts
|
|
1215
|
-
var
|
|
1216
|
-
var
|
|
1393
|
+
var import_oauth223 = require("@openid4vc/oauth2");
|
|
1394
|
+
var import_utils15 = require("@openid4vc/utils");
|
|
1217
1395
|
var jarmAuthResponseSend = (options) => {
|
|
1218
1396
|
const { authRequest, jarmAuthResponseJwt, callbacks } = options;
|
|
1219
1397
|
const responseEndpoint = authRequest.response_uri ?? authRequest.redirect_uri;
|
|
1220
1398
|
if (!responseEndpoint) {
|
|
1221
|
-
throw new
|
|
1399
|
+
throw new import_oauth223.Oauth2Error(`Either 'response_uri' or 'redirect_uri' MUST be present in the authorization request`);
|
|
1222
1400
|
}
|
|
1223
|
-
const responseEndpointUrl = new
|
|
1401
|
+
const responseEndpointUrl = new import_utils15.URL(responseEndpoint);
|
|
1224
1402
|
return handleDirectPostJwt(responseEndpointUrl, jarmAuthResponseJwt, callbacks);
|
|
1225
1403
|
};
|
|
1226
1404
|
async function handleDirectPostJwt(responseEndpoint, responseJwt, callbacks) {
|
|
1227
|
-
const response = await (callbacks.fetch ??
|
|
1405
|
+
const response = await (callbacks.fetch ?? import_utils15.defaultFetcher)(responseEndpoint, {
|
|
1228
1406
|
method: "POST",
|
|
1229
|
-
headers: { "Content-Type":
|
|
1407
|
+
headers: { "Content-Type": import_utils15.ContentType.XWwwFormUrlencoded },
|
|
1230
1408
|
body: `response=${responseJwt}`
|
|
1231
1409
|
});
|
|
1232
1410
|
return {
|
|
@@ -1237,27 +1415,27 @@ async function handleDirectPostJwt(responseEndpoint, responseJwt, callbacks) {
|
|
|
1237
1415
|
|
|
1238
1416
|
// src/authorization-response/submit-authorization-response.ts
|
|
1239
1417
|
async function submitOpenid4vpAuthorizationResponse(options) {
|
|
1240
|
-
const {
|
|
1241
|
-
const url =
|
|
1418
|
+
const { requestPayload, responsePayload, jarm, callbacks } = options;
|
|
1419
|
+
const url = requestPayload.response_uri;
|
|
1242
1420
|
if (jarm) {
|
|
1243
1421
|
return jarmAuthResponseSend({
|
|
1244
|
-
authRequest:
|
|
1422
|
+
authRequest: requestPayload,
|
|
1245
1423
|
jarmAuthResponseJwt: jarm.responseJwt,
|
|
1246
1424
|
callbacks
|
|
1247
1425
|
});
|
|
1248
1426
|
}
|
|
1249
1427
|
if (!url) {
|
|
1250
|
-
throw new
|
|
1428
|
+
throw new import_oauth224.Oauth2Error(
|
|
1251
1429
|
"Failed to submit OpenId4Vp Authorization Response. No redirect_uri or response_uri provided."
|
|
1252
1430
|
);
|
|
1253
1431
|
}
|
|
1254
|
-
const fetch = callbacks.fetch ??
|
|
1255
|
-
const encodedResponse = (0,
|
|
1432
|
+
const fetch = callbacks.fetch ?? import_utils16.defaultFetcher;
|
|
1433
|
+
const encodedResponse = (0, import_utils17.objectToQueryParams)(responsePayload);
|
|
1256
1434
|
const submissionResponse = await fetch(url, {
|
|
1257
1435
|
method: "POST",
|
|
1258
1436
|
body: encodedResponse,
|
|
1259
1437
|
headers: {
|
|
1260
|
-
"Content-Type":
|
|
1438
|
+
"Content-Type": import_utils16.ContentType.XWwwFormUrlencoded
|
|
1261
1439
|
}
|
|
1262
1440
|
});
|
|
1263
1441
|
return {
|
|
@@ -1267,33 +1445,33 @@ async function submitOpenid4vpAuthorizationResponse(options) {
|
|
|
1267
1445
|
}
|
|
1268
1446
|
|
|
1269
1447
|
// src/authorization-response/validate-authorization-response.ts
|
|
1270
|
-
var
|
|
1448
|
+
var import_oauth227 = require("@openid4vc/oauth2");
|
|
1271
1449
|
|
|
1272
1450
|
// src/vp-token/parse-presentations-from-vp-token.ts
|
|
1273
|
-
var
|
|
1274
|
-
var
|
|
1275
|
-
var
|
|
1276
|
-
var
|
|
1451
|
+
var import_oauth225 = require("@openid4vc/oauth2");
|
|
1452
|
+
var import_oauth226 = require("@openid4vc/oauth2");
|
|
1453
|
+
var import_utils18 = require("@openid4vc/utils");
|
|
1454
|
+
var import_zod17 = require("zod");
|
|
1277
1455
|
function parsePresentationsFromVpToken(options) {
|
|
1278
1456
|
const { vpToken: _vpToken } = options;
|
|
1279
|
-
const vpToken = (0,
|
|
1457
|
+
const vpToken = (0, import_utils18.parseIfJson)(_vpToken);
|
|
1280
1458
|
if (Array.isArray(vpToken)) {
|
|
1281
1459
|
if (vpToken.length === 0) {
|
|
1282
|
-
throw new
|
|
1460
|
+
throw new import_oauth225.Oauth2Error("Could not parse vp_token. vp_token is an empty array.");
|
|
1283
1461
|
}
|
|
1284
1462
|
return vpToken.map((token, idx) => parseSinglePresentationFromVpToken({ vpToken: token, path: `$[${idx}]` }));
|
|
1285
1463
|
}
|
|
1286
1464
|
if (typeof vpToken === "string" || typeof vpToken === "object") {
|
|
1287
1465
|
return [parseSinglePresentationFromVpToken({ vpToken, path: "$" })];
|
|
1288
1466
|
}
|
|
1289
|
-
throw new
|
|
1467
|
+
throw new import_oauth225.Oauth2Error(
|
|
1290
1468
|
`Could not parse vp_token. Expected a string or an array of strings. Received: ${typeof vpToken}`
|
|
1291
1469
|
);
|
|
1292
1470
|
}
|
|
1293
1471
|
function parseDcqlPresentationFromVpToken(options) {
|
|
1294
1472
|
const { vpToken: _vpToken } = options;
|
|
1295
|
-
const vpToken = (0,
|
|
1296
|
-
const parsed = (0,
|
|
1473
|
+
const vpToken = (0, import_utils18.parseIfJson)(_vpToken);
|
|
1474
|
+
const parsed = (0, import_utils18.parseWithErrorHandling)(import_zod17.z.object({}).passthrough(), vpToken);
|
|
1297
1475
|
const dcqlPresentationRecord = Object.fromEntries(
|
|
1298
1476
|
Object.entries(parsed).map(([key, value]) => {
|
|
1299
1477
|
return [key, parseSinglePresentationFromVpToken({ vpToken: value })];
|
|
@@ -1303,25 +1481,25 @@ function parseDcqlPresentationFromVpToken(options) {
|
|
|
1303
1481
|
}
|
|
1304
1482
|
function parseSinglePresentationFromVpToken(options) {
|
|
1305
1483
|
const { vpToken: _vpToken, path } = options;
|
|
1306
|
-
const vpToken = (0,
|
|
1307
|
-
const zLdpVpProof =
|
|
1308
|
-
const ldpVpParseResult =
|
|
1309
|
-
"@context":
|
|
1310
|
-
verifiableCredential:
|
|
1311
|
-
proof:
|
|
1484
|
+
const vpToken = (0, import_utils18.parseIfJson)(_vpToken);
|
|
1485
|
+
const zLdpVpProof = import_zod17.z.object({ challenge: import_zod17.z.string().optional() }).passthrough();
|
|
1486
|
+
const ldpVpParseResult = import_zod17.z.object({
|
|
1487
|
+
"@context": import_zod17.z.string().optional(),
|
|
1488
|
+
verifiableCredential: import_zod17.z.string().optional(),
|
|
1489
|
+
proof: import_zod17.z.union([zLdpVpProof, import_zod17.z.array(zLdpVpProof)]).optional()
|
|
1312
1490
|
}).passthrough().safeParse(vpToken);
|
|
1313
1491
|
if (ldpVpParseResult.success && (ldpVpParseResult.data["@context"] || ldpVpParseResult.data.verifiableCredential)) {
|
|
1314
1492
|
const challenge = Array.isArray(ldpVpParseResult.data.proof) ? ldpVpParseResult.data.proof.map((proof) => proof.challenge) : ldpVpParseResult.data.proof?.challenge;
|
|
1315
1493
|
if (Array.isArray(challenge)) {
|
|
1316
1494
|
const allNoncesAreTheSame = challenge.every((nonce) => nonce === challenge[0]);
|
|
1317
1495
|
if (!allNoncesAreTheSame) {
|
|
1318
|
-
throw new
|
|
1496
|
+
throw new import_oauth225.Oauth2Error(
|
|
1319
1497
|
"Failed to parse presentation from vp_token. LDP presentation is missing the proof.challenge parameter."
|
|
1320
1498
|
);
|
|
1321
1499
|
}
|
|
1322
1500
|
}
|
|
1323
1501
|
if (!challenge) {
|
|
1324
|
-
throw new
|
|
1502
|
+
throw new import_oauth225.Oauth2Error(
|
|
1325
1503
|
"Failed to parse presentation from vp_token. LDP presentation is missing the proof.challenge parameter."
|
|
1326
1504
|
);
|
|
1327
1505
|
}
|
|
@@ -1332,7 +1510,7 @@ function parseSinglePresentationFromVpToken(options) {
|
|
|
1332
1510
|
nonce: Array.isArray(challenge) ? challenge[0] : challenge
|
|
1333
1511
|
};
|
|
1334
1512
|
}
|
|
1335
|
-
if ((0,
|
|
1513
|
+
if ((0, import_utils18.isObject)(vpToken) && (vpToken.schema_id || vpToken.cred_def_id)) {
|
|
1336
1514
|
return {
|
|
1337
1515
|
format: "ac_vp",
|
|
1338
1516
|
presentation: vpToken,
|
|
@@ -1340,7 +1518,7 @@ function parseSinglePresentationFromVpToken(options) {
|
|
|
1340
1518
|
};
|
|
1341
1519
|
}
|
|
1342
1520
|
if (typeof vpToken !== "string") {
|
|
1343
|
-
throw new
|
|
1521
|
+
throw new import_oauth225.Oauth2Error(
|
|
1344
1522
|
`Could not parse vp_token. Expected a string since the vp_token is neither a ldp_vp nor an ac_vp. Received: ${typeof vpToken}`
|
|
1345
1523
|
);
|
|
1346
1524
|
}
|
|
@@ -1349,7 +1527,7 @@ function parseSinglePresentationFromVpToken(options) {
|
|
|
1349
1527
|
const keyBindingJwt = split[split.length - 1];
|
|
1350
1528
|
let nonce;
|
|
1351
1529
|
try {
|
|
1352
|
-
const decoded = (0,
|
|
1530
|
+
const decoded = (0, import_oauth225.decodeJwt)({ jwt: keyBindingJwt });
|
|
1353
1531
|
nonce = decoded.payload.nonce;
|
|
1354
1532
|
} catch (error) {
|
|
1355
1533
|
nonce = void 0;
|
|
@@ -1360,11 +1538,11 @@ function parseSinglePresentationFromVpToken(options) {
|
|
|
1360
1538
|
path: options.path
|
|
1361
1539
|
};
|
|
1362
1540
|
}
|
|
1363
|
-
const result =
|
|
1541
|
+
const result = import_oauth226.zCompactJwt.safeParse(vpToken);
|
|
1364
1542
|
if (result.success) {
|
|
1365
1543
|
let nonce;
|
|
1366
1544
|
try {
|
|
1367
|
-
const decoded = (0,
|
|
1545
|
+
const decoded = (0, import_oauth225.decodeJwt)({ jwt: vpToken });
|
|
1368
1546
|
nonce = decoded.payload.nonce;
|
|
1369
1547
|
} catch (error) {
|
|
1370
1548
|
nonce = void 0;
|
|
@@ -1385,98 +1563,98 @@ function parseSinglePresentationFromVpToken(options) {
|
|
|
1385
1563
|
|
|
1386
1564
|
// src/authorization-response/validate-authorization-response.ts
|
|
1387
1565
|
function validateOpenid4vpAuthorizationResponse(options) {
|
|
1388
|
-
const {
|
|
1389
|
-
if (!
|
|
1390
|
-
throw new
|
|
1566
|
+
const { requestPayload, responsePayload } = options;
|
|
1567
|
+
if (!responsePayload.vp_token) {
|
|
1568
|
+
throw new import_oauth227.Oauth2Error("Failed to verify OpenId4Vp Authorization Response. vp_token is missing.");
|
|
1391
1569
|
}
|
|
1392
|
-
if ("state" in
|
|
1393
|
-
throw new
|
|
1570
|
+
if ("state" in requestPayload && requestPayload.state !== responsePayload.state) {
|
|
1571
|
+
throw new import_oauth227.Oauth2Error("OpenId4Vp Authorization Response state mismatch.");
|
|
1394
1572
|
}
|
|
1395
|
-
if (
|
|
1396
|
-
throw new
|
|
1573
|
+
if (responsePayload.id_token) {
|
|
1574
|
+
throw new import_oauth227.Oauth2Error("OpenId4Vp Authorization Response id_token is not supported.");
|
|
1397
1575
|
}
|
|
1398
|
-
if (
|
|
1399
|
-
if (!
|
|
1400
|
-
throw new
|
|
1576
|
+
if (responsePayload.presentation_submission) {
|
|
1577
|
+
if (!requestPayload.presentation_definition) {
|
|
1578
|
+
throw new import_oauth227.Oauth2Error("OpenId4Vp Authorization Request is missing the required presentation_definition.");
|
|
1401
1579
|
}
|
|
1402
|
-
const presentations = parsePresentationsFromVpToken({ vpToken:
|
|
1403
|
-
if (presentations.every((p) => p.nonce) && !presentations.every((p) => p.nonce ===
|
|
1404
|
-
throw new
|
|
1580
|
+
const presentations = parsePresentationsFromVpToken({ vpToken: responsePayload.vp_token });
|
|
1581
|
+
if (presentations.every((p) => p.nonce) && !presentations.every((p) => p.nonce === requestPayload.nonce)) {
|
|
1582
|
+
throw new import_oauth227.Oauth2Error(
|
|
1405
1583
|
"Presentation nonce mismatch. The nonce of some presentations does not match the nonce of the request."
|
|
1406
1584
|
);
|
|
1407
1585
|
}
|
|
1408
1586
|
return {
|
|
1409
1587
|
type: "pex",
|
|
1410
|
-
pex: "scope" in
|
|
1411
|
-
scope:
|
|
1412
|
-
presentationSubmission:
|
|
1588
|
+
pex: "scope" in requestPayload && requestPayload.scope ? {
|
|
1589
|
+
scope: requestPayload.scope,
|
|
1590
|
+
presentationSubmission: responsePayload.presentation_submission,
|
|
1413
1591
|
presentations
|
|
1414
1592
|
} : {
|
|
1415
|
-
presentationDefinition:
|
|
1416
|
-
presentationSubmission:
|
|
1593
|
+
presentationDefinition: requestPayload.presentation_definition,
|
|
1594
|
+
presentationSubmission: responsePayload.presentation_submission,
|
|
1417
1595
|
presentations
|
|
1418
1596
|
}
|
|
1419
1597
|
};
|
|
1420
1598
|
}
|
|
1421
|
-
if (
|
|
1422
|
-
if (Array.isArray(
|
|
1423
|
-
throw new
|
|
1599
|
+
if (requestPayload.dcql_query) {
|
|
1600
|
+
if (Array.isArray(responsePayload.vp_token)) {
|
|
1601
|
+
throw new import_oauth227.Oauth2Error(
|
|
1424
1602
|
"The OpenId4Vp Authorization Response contains multiple vp_token values. In combination with dcql this is not possible."
|
|
1425
1603
|
);
|
|
1426
1604
|
}
|
|
1427
|
-
if (typeof
|
|
1428
|
-
throw new
|
|
1605
|
+
if (typeof responsePayload.vp_token !== "string" && typeof responsePayload.vp_token !== "object") {
|
|
1606
|
+
throw new import_oauth227.Oauth2Error("With DCQL the vp_token must be a JSON-encoded object.");
|
|
1429
1607
|
}
|
|
1430
|
-
const presentation = parseDcqlPresentationFromVpToken({ vpToken:
|
|
1431
|
-
if (Object.values(presentation).every((p) => p.nonce) && !Object.values(presentation).every((p) => p.nonce ===
|
|
1432
|
-
throw new
|
|
1608
|
+
const presentation = parseDcqlPresentationFromVpToken({ vpToken: responsePayload.vp_token });
|
|
1609
|
+
if (Object.values(presentation).every((p) => p.nonce) && !Object.values(presentation).every((p) => p.nonce === requestPayload.nonce)) {
|
|
1610
|
+
throw new import_oauth227.Oauth2Error(
|
|
1433
1611
|
"Presentation nonce mismatch. The nonce of some presentations does not match the nonce of the request."
|
|
1434
1612
|
);
|
|
1435
1613
|
}
|
|
1436
1614
|
return {
|
|
1437
1615
|
type: "dcql",
|
|
1438
|
-
dcql: "scope" in
|
|
1439
|
-
scope:
|
|
1616
|
+
dcql: "scope" in requestPayload && requestPayload.scope ? {
|
|
1617
|
+
scope: requestPayload.scope,
|
|
1440
1618
|
presentation
|
|
1441
1619
|
} : {
|
|
1442
|
-
query:
|
|
1620
|
+
query: requestPayload.dcql_query,
|
|
1443
1621
|
presentation
|
|
1444
1622
|
}
|
|
1445
1623
|
};
|
|
1446
1624
|
}
|
|
1447
|
-
throw new
|
|
1625
|
+
throw new import_oauth227.Oauth2Error(
|
|
1448
1626
|
"Invalid OpenId4Vp Authorization Response. Response neither contains a presentation_submission nor a dcql_query."
|
|
1449
1627
|
);
|
|
1450
1628
|
}
|
|
1451
1629
|
|
|
1452
1630
|
// src/authorization-response/parse-authorization-response.ts
|
|
1453
|
-
var
|
|
1631
|
+
var import_oauth229 = require("@openid4vc/oauth2");
|
|
1454
1632
|
|
|
1455
1633
|
// src/authorization-response/parse-authorization-response-payload.ts
|
|
1456
|
-
var
|
|
1634
|
+
var import_utils19 = require("@openid4vc/utils");
|
|
1457
1635
|
|
|
1458
1636
|
// src/authorization-response/z-authorization-response.ts
|
|
1459
|
-
var
|
|
1637
|
+
var import_zod19 = require("zod");
|
|
1460
1638
|
|
|
1461
1639
|
// src/vp-token/z-vp-token.ts
|
|
1462
|
-
var
|
|
1463
|
-
var zVpToken =
|
|
1640
|
+
var import_zod18 = require("zod");
|
|
1641
|
+
var zVpToken = import_zod18.z.union([import_zod18.z.string(), import_zod18.z.array(import_zod18.z.union([import_zod18.z.string(), import_zod18.z.record(import_zod18.z.any())])), import_zod18.z.record(import_zod18.z.any())]);
|
|
1464
1642
|
|
|
1465
1643
|
// src/authorization-response/z-authorization-response.ts
|
|
1466
|
-
var zOpenid4vpAuthorizationResponse =
|
|
1467
|
-
state:
|
|
1468
|
-
id_token:
|
|
1644
|
+
var zOpenid4vpAuthorizationResponse = import_zod19.z.object({
|
|
1645
|
+
state: import_zod19.z.string().optional(),
|
|
1646
|
+
id_token: import_zod19.z.string().optional(),
|
|
1469
1647
|
vp_token: zVpToken,
|
|
1470
|
-
presentation_submission:
|
|
1471
|
-
refresh_token:
|
|
1472
|
-
token_type:
|
|
1473
|
-
access_token:
|
|
1474
|
-
expires_in:
|
|
1648
|
+
presentation_submission: import_zod19.z.unknown().optional(),
|
|
1649
|
+
refresh_token: import_zod19.z.string().optional(),
|
|
1650
|
+
token_type: import_zod19.z.string().optional(),
|
|
1651
|
+
access_token: import_zod19.z.string().optional(),
|
|
1652
|
+
expires_in: import_zod19.z.number().optional()
|
|
1475
1653
|
}).passthrough();
|
|
1476
1654
|
|
|
1477
1655
|
// src/authorization-response/parse-authorization-response-payload.ts
|
|
1478
1656
|
function parseOpenid4VpAuthorizationResponsePayload(payload) {
|
|
1479
|
-
return (0,
|
|
1657
|
+
return (0, import_utils19.parseWithErrorHandling)(
|
|
1480
1658
|
zOpenid4vpAuthorizationResponse,
|
|
1481
1659
|
payload,
|
|
1482
1660
|
"Failed to parse openid4vp authorization response."
|
|
@@ -1484,19 +1662,19 @@ function parseOpenid4VpAuthorizationResponsePayload(payload) {
|
|
|
1484
1662
|
}
|
|
1485
1663
|
|
|
1486
1664
|
// src/authorization-response/parse-jarm-authorization-response.ts
|
|
1487
|
-
var
|
|
1488
|
-
var
|
|
1489
|
-
var
|
|
1665
|
+
var import_oauth228 = require("@openid4vc/oauth2");
|
|
1666
|
+
var import_utils20 = require("@openid4vc/utils");
|
|
1667
|
+
var import_zod20 = __toESM(require("zod"));
|
|
1490
1668
|
async function parseJarmAuthorizationResponse(options) {
|
|
1491
1669
|
const { jarmResponseJwt, callbacks } = options;
|
|
1492
|
-
const jarmAuthorizationResponseJwt = (0,
|
|
1493
|
-
|
|
1670
|
+
const jarmAuthorizationResponseJwt = (0, import_utils20.parseWithErrorHandling)(
|
|
1671
|
+
import_zod20.default.union([import_oauth228.zCompactJwt, import_oauth228.zCompactJwe]),
|
|
1494
1672
|
jarmResponseJwt,
|
|
1495
1673
|
"Invalid jarm authorization response jwt."
|
|
1496
1674
|
);
|
|
1497
1675
|
const verifiedJarmResponse = await verifyJarmAuthorizationResponse({ jarmAuthorizationResponseJwt, callbacks });
|
|
1498
|
-
const zJarmHeader =
|
|
1499
|
-
const { header: jarmHeader } = (0,
|
|
1676
|
+
const zJarmHeader = import_zod20.default.object({ ...import_oauth228.zJwtHeader.shape, apu: import_zod20.default.string().optional(), apv: import_zod20.default.string().optional() });
|
|
1677
|
+
const { header: jarmHeader } = (0, import_oauth228.decodeJwtHeader)({
|
|
1500
1678
|
jwt: jarmAuthorizationResponseJwt,
|
|
1501
1679
|
headerSchema: zJarmHeader
|
|
1502
1680
|
});
|
|
@@ -1504,27 +1682,27 @@ async function parseJarmAuthorizationResponse(options) {
|
|
|
1504
1682
|
authorizationRequest: verifiedJarmResponse.authorizationRequest
|
|
1505
1683
|
});
|
|
1506
1684
|
if (parsedAuthorizationRequest.type !== "openid4vp" && parsedAuthorizationRequest.type !== "openid4vp_dc_api") {
|
|
1507
|
-
throw new
|
|
1685
|
+
throw new import_oauth228.Oauth2Error("Invalid authorization request. Could not parse openid4vp authorization request.");
|
|
1508
1686
|
}
|
|
1509
1687
|
const authResponsePayload = parseOpenid4VpAuthorizationResponsePayload(verifiedJarmResponse.jarmAuthResponse);
|
|
1510
1688
|
const validateOpenId4vpResponse = validateOpenid4vpAuthorizationResponse({
|
|
1511
|
-
|
|
1512
|
-
|
|
1689
|
+
requestPayload: parsedAuthorizationRequest.params,
|
|
1690
|
+
responsePayload: authResponsePayload
|
|
1513
1691
|
});
|
|
1514
1692
|
const authRequestPayload = parsedAuthorizationRequest.params;
|
|
1515
1693
|
if (!authRequestPayload.response_mode || !isJarmResponseMode(authRequestPayload.response_mode)) {
|
|
1516
|
-
throw new
|
|
1694
|
+
throw new import_oauth228.Oauth2Error(
|
|
1517
1695
|
`Invalid response mode for jarm response. Response mode: '${authRequestPayload.response_mode ?? "fragment"}'`
|
|
1518
1696
|
);
|
|
1519
1697
|
}
|
|
1520
1698
|
let mdocGeneratedNonce = void 0;
|
|
1521
1699
|
if (jarmHeader?.apu) {
|
|
1522
|
-
mdocGeneratedNonce = (0,
|
|
1700
|
+
mdocGeneratedNonce = (0, import_utils20.encodeToUtf8String)((0, import_utils20.decodeBase64)(jarmHeader.apu));
|
|
1523
1701
|
}
|
|
1524
1702
|
if (jarmHeader?.apv) {
|
|
1525
|
-
const jarmRequestNonce = (0,
|
|
1703
|
+
const jarmRequestNonce = (0, import_utils20.encodeToUtf8String)((0, import_utils20.decodeBase64)(jarmHeader.apv));
|
|
1526
1704
|
if (jarmRequestNonce !== authRequestPayload.nonce) {
|
|
1527
|
-
throw new
|
|
1705
|
+
throw new import_oauth228.Oauth2Error("The nonce in the jarm header does not match the nonce in the request.");
|
|
1528
1706
|
}
|
|
1529
1707
|
}
|
|
1530
1708
|
return {
|
|
@@ -1545,15 +1723,15 @@ async function parseOpenid4vpAuthorizationResponse(options) {
|
|
|
1545
1723
|
const { authorizationRequest } = await callbacks.getOpenid4vpAuthorizationRequest(authResponsePayload);
|
|
1546
1724
|
const parsedAuthRequest = parseOpenid4vpAuthorizationRequestPayload({ authorizationRequest });
|
|
1547
1725
|
if (parsedAuthRequest.type !== "openid4vp" && parsedAuthRequest.type !== "openid4vp_dc_api") {
|
|
1548
|
-
throw new
|
|
1726
|
+
throw new import_oauth229.Oauth2Error("Invalid authorization request. Could not parse openid4vp authorization request.");
|
|
1549
1727
|
}
|
|
1550
1728
|
const authRequestPayload = parsedAuthRequest.params;
|
|
1551
1729
|
const validateOpenId4vpResponse = validateOpenid4vpAuthorizationResponse({
|
|
1552
|
-
|
|
1553
|
-
|
|
1730
|
+
requestPayload: authRequestPayload,
|
|
1731
|
+
responsePayload: authResponsePayload
|
|
1554
1732
|
});
|
|
1555
1733
|
if (authRequestPayload.response_mode && isJarmResponseMode(authRequestPayload.response_mode)) {
|
|
1556
|
-
throw new
|
|
1734
|
+
throw new import_oauth229.Oauth2ServerErrorResponseError(
|
|
1557
1735
|
{
|
|
1558
1736
|
error: "invalid_request",
|
|
1559
1737
|
error_description: "Invalid response mode for openid4vp response. Expected jarm response."
|
|
@@ -1616,23 +1794,12 @@ var Openid4vpVerifier = class {
|
|
|
1616
1794
|
};
|
|
1617
1795
|
|
|
1618
1796
|
// src/models/z-credential-formats.ts
|
|
1619
|
-
var import_zod20 = require("zod");
|
|
1620
|
-
var zCredentialFormat = import_zod20.z.enum(["jwt_vc_json", "ldp_vc", "ac_vc", "mso_mdoc", "dc+sd-jwt"]);
|
|
1621
|
-
|
|
1622
|
-
// src/models/z-proof-formats.ts
|
|
1623
1797
|
var import_zod21 = require("zod");
|
|
1624
|
-
var
|
|
1798
|
+
var zCredentialFormat = import_zod21.z.enum(["jwt_vc_json", "ldp_vc", "ac_vc", "mso_mdoc", "dc+sd-jwt", "vc+sd-jwt"]);
|
|
1625
1799
|
|
|
1626
|
-
// src/models/z-
|
|
1800
|
+
// src/models/z-proof-formats.ts
|
|
1627
1801
|
var import_zod22 = require("zod");
|
|
1628
|
-
var
|
|
1629
|
-
presentation_definition_uri_supported: import_zod22.z.optional(import_zod22.z.boolean()),
|
|
1630
|
-
vp_formats_supported: zVpFormatsSupported,
|
|
1631
|
-
client_id_schemes_supported: import_zod22.z.optional(import_zod22.z.array(zClientIdScheme)),
|
|
1632
|
-
request_object_signing_alg_values_supported: import_zod22.z.optional(import_zod22.z.array(import_zod22.z.string())),
|
|
1633
|
-
authorization_encryption_alg_values_supported: import_zod22.z.optional(import_zod22.z.array(import_zod22.z.string())),
|
|
1634
|
-
authorization_encryption_enc_values_supported: import_zod22.z.optional(import_zod22.z.array(import_zod22.z.string()))
|
|
1635
|
-
});
|
|
1802
|
+
var zProofFormat = import_zod22.z.enum(["jwt_vp_json", "ldc_vp", "ac_vp", "dc+sd-jwt", "vc+sd-jwt", "mso_mdoc"]);
|
|
1636
1803
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1637
1804
|
0 && (module.exports = {
|
|
1638
1805
|
Openid4vpClient,
|