@openeudi/openid4vp 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -147,10 +147,10 @@ var init_errors = __esm({
147
147
  code = "unsupported_jwe";
148
148
  alg;
149
149
  enc;
150
- constructor(alg, enc) {
151
- super(`Unsupported JWE algorithms: alg=${alg}, enc=${enc}`);
150
+ constructor(alg, enc3) {
151
+ super(`Unsupported JWE algorithms: alg=${alg}, enc=${enc3}`);
152
152
  this.alg = alg;
153
- this.enc = enc;
153
+ this.enc = enc3;
154
154
  }
155
155
  };
156
156
  exports.DecryptionFailedError = class extends exports.OpenID4VPError {
@@ -334,9 +334,9 @@ var init_index_es = __esm({
334
334
  static isBase64Url(data) {
335
335
  return typeof data === STRING_TYPE && BASE64URL_REGEX.test(data);
336
336
  }
337
- static ToString(buffer, enc = "utf8") {
337
+ static ToString(buffer, enc3 = "utf8") {
338
338
  const buf = BufferSourceConverter.toUint8Array(buffer);
339
- switch (enc.toLowerCase()) {
339
+ switch (enc3.toLowerCase()) {
340
340
  case "utf8":
341
341
  return this.ToUtf8String(buf);
342
342
  case "binary":
@@ -353,14 +353,14 @@ var init_index_es = __esm({
353
353
  case "utf16be":
354
354
  return Utf16Converter.toString(buf);
355
355
  default:
356
- throw new Error(`Unknown type of encoding '${enc}'`);
356
+ throw new Error(`Unknown type of encoding '${enc3}'`);
357
357
  }
358
358
  }
359
- static FromString(str, enc = "utf8") {
359
+ static FromString(str, enc3 = "utf8") {
360
360
  if (!str) {
361
361
  return new ArrayBuffer(0);
362
362
  }
363
- switch (enc.toLowerCase()) {
363
+ switch (enc3.toLowerCase()) {
364
364
  case "utf8":
365
365
  return this.FromUtf8String(str);
366
366
  case "binary":
@@ -377,7 +377,7 @@ var init_index_es = __esm({
377
377
  case "utf16be":
378
378
  return Utf16Converter.fromString(str);
379
379
  default:
380
- throw new Error(`Unknown type of encoding '${enc}'`);
380
+ throw new Error(`Unknown type of encoding '${enc3}'`);
381
381
  }
382
382
  }
383
383
  static ToBase64(buffer) {
@@ -8191,8 +8191,8 @@ async function createSignedAuthorizationRequest(input, query) {
8191
8191
  vp_formats_supported: input.vpFormatsSupported
8192
8192
  };
8193
8193
  if (responseMode === "direct_post.jwt" && input.encryptionKey) {
8194
- const enc = input.encryptionKey.supportedEncValues;
8195
- if (enc !== void 0 && enc.length === 0) {
8194
+ const enc3 = input.encryptionKey.supportedEncValues;
8195
+ if (enc3 !== void 0 && enc3.length === 0) {
8196
8196
  throw new exports.SignedRequestBuildError(
8197
8197
  "empty_supported_enc_values",
8198
8198
  "encryptionKey.supportedEncValues must not be empty (omit to use defaults [A128GCM, A256GCM])"
@@ -8200,7 +8200,7 @@ async function createSignedAuthorizationRequest(input, query) {
8200
8200
  }
8201
8201
  const jwk = { ...input.encryptionKey.publicJwk, use: "enc" };
8202
8202
  clientMetadata.jwks = { keys: [jwk] };
8203
- const encValues = enc ?? [...DEFAULT_SUPPORTED_ENC_VALUES];
8203
+ const encValues = enc3 ?? [...DEFAULT_SUPPORTED_ENC_VALUES];
8204
8204
  clientMetadata.encrypted_response_enc_values_supported = encValues;
8205
8205
  clientMetadata.authorization_encrypted_response_alg = "ECDH-ES";
8206
8206
  clientMetadata.authorization_encrypted_response_enc = encValues[0];
@@ -8474,6 +8474,131 @@ async function verifyCoseSign1(coseSign1, publicKey, allowedAlgorithms) {
8474
8474
  }
8475
8475
  }
8476
8476
 
8477
+ // src/crypto/device-auth.ts
8478
+ init_errors();
8479
+ var enc = new cborX.Encoder({ mapsAsObjects: false, useRecords: false, tagUint8Array: false });
8480
+ var HEADER_ALG2 = 1;
8481
+ var COSE_ALG_TO_NAME2 = {
8482
+ [-7]: "ES256",
8483
+ [-35]: "ES384",
8484
+ [-36]: "ES512"
8485
+ };
8486
+ var ALG_TO_HASH2 = { ES256: "SHA-256", ES384: "SHA-384", ES512: "SHA-512" };
8487
+ var COSE_KEY_KTY = 1;
8488
+ var COSE_KEY_CRV = -1;
8489
+ var COSE_KEY_X = -2;
8490
+ var COSE_KEY_Y = -3;
8491
+ var COSE_KTY_EC2 = 2;
8492
+ var COSE_CRV_TO_JWK = { 1: "P-256", 2: "P-384", 3: "P-521" };
8493
+ function concatBytes(...chunks) {
8494
+ let len = 0;
8495
+ for (const c of chunks) len += c.length;
8496
+ const out = new Uint8Array(len);
8497
+ let off = 0;
8498
+ for (const c of chunks) {
8499
+ out.set(c, off);
8500
+ off += c.length;
8501
+ }
8502
+ return out;
8503
+ }
8504
+ function bytesToBase64Url(bytes) {
8505
+ let bin = "";
8506
+ for (const b of bytes) bin += String.fromCharCode(b);
8507
+ return globalThis.btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
8508
+ }
8509
+ function encodeTag24(inner) {
8510
+ return concatBytes(new Uint8Array([216, 24]), new Uint8Array(enc.encode(inner)));
8511
+ }
8512
+ function buildDeviceAuthenticationBytes(params) {
8513
+ const deviceAuthentication = concatBytes(
8514
+ new Uint8Array([132]),
8515
+ // array(4)
8516
+ new Uint8Array(enc.encode("DeviceAuthentication")),
8517
+ params.sessionTranscript,
8518
+ new Uint8Array(enc.encode(params.docType)),
8519
+ encodeTag24(params.deviceNameSpacesInner)
8520
+ );
8521
+ return encodeTag24(deviceAuthentication);
8522
+ }
8523
+ function encodeDeviceSigStructure(protectedBytes, deviceAuthBytes) {
8524
+ const sig = ["Signature1", protectedBytes, new Uint8Array(0), deviceAuthBytes];
8525
+ return new Uint8Array(enc.encode(sig));
8526
+ }
8527
+ async function importDeviceKeyFromCose(coseKey) {
8528
+ if (!(coseKey instanceof Map)) {
8529
+ throw new exports.MalformedCredentialError("MSO deviceKeyInfo.deviceKey is not a COSE_Key map");
8530
+ }
8531
+ const kty = coseKey.get(COSE_KEY_KTY);
8532
+ if (kty !== COSE_KTY_EC2) {
8533
+ throw new exports.MalformedCredentialError(`Unsupported COSE key type for device key: ${String(kty)}`);
8534
+ }
8535
+ const crv = coseKey.get(COSE_KEY_CRV);
8536
+ const crvName = typeof crv === "number" ? COSE_CRV_TO_JWK[crv] : void 0;
8537
+ const x = coseKey.get(COSE_KEY_X);
8538
+ const y = coseKey.get(COSE_KEY_Y);
8539
+ if (!crvName || !(x instanceof Uint8Array) || !(y instanceof Uint8Array)) {
8540
+ throw new exports.MalformedCredentialError("Malformed EC2 COSE_Key in MSO deviceKeyInfo");
8541
+ }
8542
+ return crypto.subtle.importKey(
8543
+ "jwk",
8544
+ { kty: "EC", crv: crvName, x: bytesToBase64Url(x), y: bytesToBase64Url(y) },
8545
+ { name: "ECDSA", namedCurve: crvName },
8546
+ false,
8547
+ ["verify"]
8548
+ );
8549
+ }
8550
+ async function verifyDeviceAuth(params) {
8551
+ const { deviceSigned, deviceKeyCose, docType, sessionTranscript, allowedAlgorithms } = params;
8552
+ const deviceAuth = deviceSigned.get("deviceAuth");
8553
+ if (!(deviceAuth instanceof Map)) {
8554
+ throw new exports.MalformedCredentialError("deviceSigned.deviceAuth is missing or malformed");
8555
+ }
8556
+ if (deviceAuth.has("deviceMac") && !deviceAuth.has("deviceSignature")) {
8557
+ throw new exports.MalformedCredentialError("mDOC DeviceMac authentication is not supported");
8558
+ }
8559
+ const deviceSignature = deviceAuth.get("deviceSignature");
8560
+ if (!Array.isArray(deviceSignature) || deviceSignature.length !== 4) {
8561
+ throw new exports.MalformedCredentialError("deviceAuth.deviceSignature must be a COSE_Sign1 array");
8562
+ }
8563
+ const protectedBytes = deviceSignature[0];
8564
+ const signature = deviceSignature[3];
8565
+ if (!(protectedBytes instanceof Uint8Array) || !(signature instanceof Uint8Array)) {
8566
+ throw new exports.MalformedCredentialError("DeviceSignature protected header / signature must be byte strings");
8567
+ }
8568
+ let alg;
8569
+ try {
8570
+ const ph = enc.decode(protectedBytes);
8571
+ const label = ph instanceof Map ? ph.get(HEADER_ALG2) : void 0;
8572
+ alg = typeof label === "number" ? COSE_ALG_TO_NAME2[label] : void 0;
8573
+ } catch {
8574
+ throw new exports.MalformedCredentialError("DeviceSignature protected header is not decodable CBOR");
8575
+ }
8576
+ if (!alg || !allowedAlgorithms.includes(alg)) {
8577
+ throw new exports.MalformedCredentialError(`DeviceSignature uses a disallowed algorithm: ${String(alg)}`);
8578
+ }
8579
+ const deviceNameSpacesInner = extractTag24Inner(deviceSigned.get("nameSpaces"));
8580
+ const deviceAuthBytes = buildDeviceAuthenticationBytes({ sessionTranscript, docType, deviceNameSpacesInner });
8581
+ const sigInput = encodeDeviceSigStructure(protectedBytes, deviceAuthBytes);
8582
+ const deviceKey = await importDeviceKeyFromCose(deviceKeyCose);
8583
+ const ok = await crypto.subtle.verify(
8584
+ { name: "ECDSA", hash: ALG_TO_HASH2[alg] },
8585
+ deviceKey,
8586
+ new Uint8Array(signature),
8587
+ sigInput
8588
+ );
8589
+ if (!ok) {
8590
+ throw new exports.MalformedCredentialError("mDOC device authentication (DeviceSignature) failed to verify");
8591
+ }
8592
+ }
8593
+ function extractTag24Inner(value) {
8594
+ if (value instanceof Uint8Array) return value;
8595
+ if (value !== null && typeof value === "object" && "value" in value && value.value instanceof Uint8Array && // Tag(24,bytes) and EmbeddedCbor both expose .value; both are fine here.
8596
+ ("tag" in value ? value.tag === 24 : true)) {
8597
+ return value.value;
8598
+ }
8599
+ throw new exports.MalformedCredentialError("deviceSigned.nameSpaces must be tag-24 wrapped CBOR");
8600
+ }
8601
+
8477
8602
  // src/crypto/digest.ts
8478
8603
  init_errors();
8479
8604
  var decoder2 = new cborX.Encoder({ mapsAsObjects: false, useRecords: false });
@@ -8606,6 +8731,14 @@ function decodeMso(payload) {
8606
8731
  }
8607
8732
  valueDigests.set(ns, perNs);
8608
8733
  }
8734
+ let deviceKey;
8735
+ const dkiRaw = m.get("deviceKeyInfo");
8736
+ if (dkiRaw instanceof Map) {
8737
+ const dk = dkiRaw.get("deviceKey");
8738
+ if (dk instanceof Map) {
8739
+ deviceKey = dk;
8740
+ }
8741
+ }
8609
8742
  const viRaw = m.get("validityInfo");
8610
8743
  if (!(viRaw instanceof Map)) {
8611
8744
  throw new exports.MalformedCredentialError("MSO.validityInfo must be a Map");
@@ -8619,7 +8752,7 @@ function decodeMso(payload) {
8619
8752
  if (vi.has("expectedUpdate")) {
8620
8753
  validityInfo.expectedUpdate = decodeDateLike(vi.get("expectedUpdate"));
8621
8754
  }
8622
- return { version, digestAlgorithm, valueDigests, docType, validityInfo };
8755
+ return { version, digestAlgorithm, valueDigests, docType, deviceKey, validityInfo };
8623
8756
  }
8624
8757
  function validateMsoValidity(mso, now) {
8625
8758
  const { signed, validFrom, validUntil } = mso.validityInfo;
@@ -8669,15 +8802,54 @@ ${lines.join("\n")}
8669
8802
  function extractCountryHintFromCert(_certDer) {
8670
8803
  return "";
8671
8804
  }
8805
+ function cborByteStringHeader(length) {
8806
+ if (length < 24) return Uint8Array.of(64 | length);
8807
+ if (length < 256) return Uint8Array.of(88, length);
8808
+ if (length < 65536) return Uint8Array.of(89, length >> 8 & 255, length & 255);
8809
+ if (length < 4294967296) {
8810
+ return Uint8Array.of(
8811
+ 90,
8812
+ length >>> 24 & 255,
8813
+ length >>> 16 & 255,
8814
+ length >>> 8 & 255,
8815
+ length & 255
8816
+ );
8817
+ }
8818
+ const hi = Math.floor(length / 4294967296);
8819
+ const lo = length >>> 0;
8820
+ return Uint8Array.of(
8821
+ 91,
8822
+ hi >>> 24 & 255,
8823
+ hi >>> 16 & 255,
8824
+ hi >>> 8 & 255,
8825
+ hi & 255,
8826
+ lo >>> 24 & 255,
8827
+ lo >>> 16 & 255,
8828
+ lo >>> 8 & 255,
8829
+ lo & 255
8830
+ );
8831
+ }
8832
+ function wrapIssuerSignedItemBytes(inner) {
8833
+ const header = cborByteStringHeader(inner.length);
8834
+ const out = new Uint8Array(2 + header.length + inner.length);
8835
+ out[0] = 216;
8836
+ out[1] = 24;
8837
+ out.set(header, 2);
8838
+ out.set(inner, 2 + header.length);
8839
+ return out;
8840
+ }
8672
8841
  function extractRawItemBytes(item) {
8673
8842
  if (item instanceof cborX.Tag && item.tag === 24 && item.value instanceof Uint8Array) {
8674
- return item.value;
8843
+ return wrapIssuerSignedItemBytes(item.value);
8675
8844
  }
8676
8845
  if (item instanceof Uint8Array) {
8677
- return item;
8846
+ if (item.length >= 2 && item[0] === 216 && item[1] === 24) {
8847
+ return item;
8848
+ }
8849
+ return wrapIssuerSignedItemBytes(item);
8678
8850
  }
8679
8851
  if (item !== null && typeof item === "object" && !(item instanceof cborX.Tag) && !(item instanceof Map) && "value" in item && item.value instanceof Uint8Array) {
8680
- return item.value;
8852
+ return wrapIssuerSignedItemBytes(item.value);
8681
8853
  }
8682
8854
  throw new exports.MalformedCredentialError("IssuerSignedItem must be a tag-24 byte string");
8683
8855
  }
@@ -8867,6 +9039,54 @@ var MdocParser = class {
8867
9039
  nameSpaces.set(ns, items.map(extractRawItemBytes));
8868
9040
  }
8869
9041
  await verifyAllDigests(nameSpaces, mso);
9042
+ const deviceSigned = document.get("deviceSigned");
9043
+ if (!(deviceSigned instanceof Map)) {
9044
+ return {
9045
+ valid: false,
9046
+ format: this.format,
9047
+ claims: {},
9048
+ issuer: { certificate: issuerCertBytes, country: "" },
9049
+ error: "Missing deviceSigned \u2014 mDOC device authentication is required"
9050
+ };
9051
+ }
9052
+ if (!(options.mdocSessionTranscript instanceof Uint8Array) || options.mdocSessionTranscript.length === 0) {
9053
+ return {
9054
+ valid: false,
9055
+ format: this.format,
9056
+ claims: {},
9057
+ issuer: { certificate: issuerCertBytes, country: "" },
9058
+ error: "mdocSessionTranscript is required to verify mDOC device authentication"
9059
+ };
9060
+ }
9061
+ if (!mso.deviceKey) {
9062
+ return {
9063
+ valid: false,
9064
+ format: this.format,
9065
+ claims: {},
9066
+ issuer: { certificate: issuerCertBytes, country: "" },
9067
+ error: "MSO is missing deviceKeyInfo.deviceKey; cannot verify device authentication"
9068
+ };
9069
+ }
9070
+ try {
9071
+ await verifyDeviceAuth({
9072
+ deviceSigned,
9073
+ deviceKeyCose: mso.deviceKey,
9074
+ docType: mso.docType,
9075
+ sessionTranscript: options.mdocSessionTranscript,
9076
+ allowedAlgorithms
9077
+ });
9078
+ } catch (err) {
9079
+ if (err instanceof exports.MalformedCredentialError) {
9080
+ return {
9081
+ valid: false,
9082
+ format: this.format,
9083
+ claims: {},
9084
+ issuer: { certificate: issuerCertBytes, country: "" },
9085
+ error: err.message
9086
+ };
9087
+ }
9088
+ throw err;
9089
+ }
8870
9090
  const { flat: claims, namespaced: namespacedClaims } = mapRawToClaims(nameSpaces);
8871
9091
  const issuer = {
8872
9092
  certificate: issuerCertBytes,
@@ -9139,11 +9359,21 @@ var SdJwtParser = class {
9139
9359
  return invalidResult("Disclosure hash mismatch");
9140
9360
  }
9141
9361
  }
9362
+ const cnf = payload["cnf"];
9363
+ const isHolderBound = !!cnf && typeof cnf === "object" && !!cnf["jwk"];
9364
+ const keyBindingRequired = isHolderBound || options.requireKeyBinding === true;
9365
+ if (keyBindingRequired && !parts.kbJwt) {
9366
+ return invalidResult(
9367
+ "Key binding JWT is required for holder-bound credentials but was not presented"
9368
+ );
9369
+ }
9142
9370
  if (parts.kbJwt) {
9143
- const cnf = payload["cnf"];
9144
- if (!cnf || typeof cnf !== "object" || !cnf["jwk"]) {
9371
+ if (!isHolderBound) {
9145
9372
  throw new exports.MalformedCredentialError("Missing cnf.jwk in issuer JWT for key binding");
9146
9373
  }
9374
+ if (typeof options.nonce !== "string" || options.nonce.length === 0) {
9375
+ return invalidResult("A nonce is required to verify the key binding JWT");
9376
+ }
9147
9377
  let holderKey;
9148
9378
  try {
9149
9379
  const kbHeader = jose.decodeProtectedHeader(parts.kbJwt);
@@ -9261,9 +9491,9 @@ async function decryptAuthorizationResponse(jwe, privateKey) {
9261
9491
  });
9262
9492
  }
9263
9493
  const alg = typeof header.alg === "string" ? header.alg : "";
9264
- const enc = typeof header.enc === "string" ? header.enc : "";
9265
- if (alg !== SUPPORTED_ALG || !SUPPORTED_ENC.has(enc)) {
9266
- throw new exports.UnsupportedJweError(alg, enc);
9494
+ const enc3 = typeof header.enc === "string" ? header.enc : "";
9495
+ if (alg !== SUPPORTED_ALG || !SUPPORTED_ENC.has(enc3)) {
9496
+ throw new exports.UnsupportedJweError(alg, enc3);
9267
9497
  }
9268
9498
  let plaintext;
9269
9499
  try {
@@ -9281,6 +9511,29 @@ async function decryptAuthorizationResponse(jwe, privateKey) {
9281
9511
  });
9282
9512
  }
9283
9513
  }
9514
+ var enc2 = new cborX.Encoder({ mapsAsObjects: false, useRecords: false, tagUint8Array: false });
9515
+ async function sha256(bytes) {
9516
+ return new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));
9517
+ }
9518
+ async function buildOid4vpSessionTranscript(params) {
9519
+ const { clientId, responseUri, nonce, mdocGeneratedNonce } = params;
9520
+ const clientIdHash = await sha256(new Uint8Array(enc2.encode([clientId, mdocGeneratedNonce])));
9521
+ const responseUriHash = await sha256(new Uint8Array(enc2.encode([responseUri, mdocGeneratedNonce])));
9522
+ return new Uint8Array(enc2.encode([null, null, [clientIdHash, responseUriHash, nonce]]));
9523
+ }
9524
+ async function jwkSha256Thumbprint(jwk) {
9525
+ if (jwk.kty !== "EC") {
9526
+ throw new Error(`Unsupported JWK kty for thumbprint: ${jwk.kty}`);
9527
+ }
9528
+ const canonical = `{"crv":"${jwk.crv}","kty":"EC","x":"${jwk.x}","y":"${jwk.y}"}`;
9529
+ return sha256(new TextEncoder().encode(canonical));
9530
+ }
9531
+ async function buildOpenID4VPHandoverSessionTranscript(params) {
9532
+ const { clientId, nonce, responseUri, verifierEncryptionJwk } = params;
9533
+ const thumb = verifierEncryptionJwk ? await jwkSha256Thumbprint(verifierEncryptionJwk) : null;
9534
+ const infoHash = await sha256(new Uint8Array(enc2.encode([clientId, nonce, thumb, responseUri])));
9535
+ return new Uint8Array(enc2.encode([null, null, ["OpenID4VPHandover", infoHash]]));
9536
+ }
9284
9537
 
9285
9538
  // src/verify.ts
9286
9539
  init_errors();
@@ -9318,6 +9571,42 @@ async function verifyPresentation(vpToken, query, options) {
9318
9571
  function isEncryptedResponse(x) {
9319
9572
  return typeof x === "object" && x !== null && "response" in x && typeof x.response === "string" && Object.keys(x).length === 1;
9320
9573
  }
9574
+ var BASE64URL_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
9575
+ function base64UrlToBytes(input) {
9576
+ const cleaned = input.replace(/=+$/, "");
9577
+ const byteLength = Math.floor(cleaned.length * 3 / 4);
9578
+ const bytes = new Uint8Array(byteLength);
9579
+ let byteIndex = 0;
9580
+ for (let i = 0; i < cleaned.length; i += 4) {
9581
+ const a = BASE64URL_CHARS.indexOf(cleaned[i]);
9582
+ const b = i + 1 < cleaned.length ? BASE64URL_CHARS.indexOf(cleaned[i + 1]) : 0;
9583
+ const c = i + 2 < cleaned.length ? BASE64URL_CHARS.indexOf(cleaned[i + 2]) : 0;
9584
+ const d = i + 3 < cleaned.length ? BASE64URL_CHARS.indexOf(cleaned[i + 3]) : 0;
9585
+ if (a === -1 || b === -1 || c === -1 || d === -1) {
9586
+ throw new TypeError("Invalid base64url character in vp_token/apu");
9587
+ }
9588
+ bytes[byteIndex++] = a << 2 | b >> 4;
9589
+ if (byteIndex < byteLength) bytes[byteIndex++] = (b & 15) << 4 | c >> 2;
9590
+ if (byteIndex < byteLength) bytes[byteIndex++] = (c & 3) << 6 | d;
9591
+ }
9592
+ return bytes;
9593
+ }
9594
+ function extractMdocGeneratedNonce(jwe) {
9595
+ let apu;
9596
+ try {
9597
+ apu = jose.decodeProtectedHeader(jwe).apu;
9598
+ } catch {
9599
+ return void 0;
9600
+ }
9601
+ if (typeof apu !== "string" || apu.length === 0) {
9602
+ return void 0;
9603
+ }
9604
+ try {
9605
+ return new TextDecoder().decode(base64UrlToBytes(apu));
9606
+ } catch {
9607
+ return void 0;
9608
+ }
9609
+ }
9321
9610
  function isAuthorizationResponse(x) {
9322
9611
  return typeof x === "object" && x !== null && "vp_token" in x && typeof x.vp_token === "object" && x.vp_token !== null;
9323
9612
  }
@@ -9326,11 +9615,32 @@ async function verifyAuthorizationResponse(envelope, query, options) {
9326
9615
  if (!options.decryptionKey) {
9327
9616
  throw new exports.MissingDecryptionKeyError();
9328
9617
  }
9618
+ const nextOptions = { ...options };
9619
+ if (options.mdocSessionTranscript === void 0 && options.clientId !== void 0 && options.responseUri !== void 0 && options.nonce !== void 0) {
9620
+ if (options.sessionTranscriptProfile === "openid4vp-1.0") {
9621
+ nextOptions.mdocSessionTranscript = await buildOpenID4VPHandoverSessionTranscript({
9622
+ clientId: options.clientId,
9623
+ nonce: options.nonce,
9624
+ responseUri: options.responseUri,
9625
+ verifierEncryptionJwk: options.verifierEncryptionJwk
9626
+ });
9627
+ } else {
9628
+ const mdocGeneratedNonce = extractMdocGeneratedNonce(envelope.response);
9629
+ if (mdocGeneratedNonce !== void 0) {
9630
+ nextOptions.mdocSessionTranscript = await buildOid4vpSessionTranscript({
9631
+ clientId: options.clientId,
9632
+ responseUri: options.responseUri,
9633
+ nonce: options.nonce,
9634
+ mdocGeneratedNonce
9635
+ });
9636
+ }
9637
+ }
9638
+ }
9329
9639
  const decrypted = await decryptAuthorizationResponse(
9330
9640
  envelope.response,
9331
9641
  options.decryptionKey
9332
9642
  );
9333
- return verifyAuthorizationResponse(decrypted, query, options);
9643
+ return verifyAuthorizationResponse(decrypted, query, nextOptions);
9334
9644
  }
9335
9645
  if (!isAuthorizationResponse(envelope)) {
9336
9646
  throw new TypeError("envelope must contain vp_token as a JSON object per OpenID4VP 1.0 \xA78.1");
@@ -9355,7 +9665,8 @@ async function verifyAuthorizationResponse(envelope, query, options) {
9355
9665
  throw new exports.MultipleCredentialsNotSupportedError(queryIds.length, presentationCount);
9356
9666
  }
9357
9667
  const presentation = vpToken[queryIds[0]][0];
9358
- return verifyPresentation(presentation, query, options);
9668
+ const decodedPresentation = query.credentials[0]?.format === "mso_mdoc" && typeof presentation === "string" ? base64UrlToBytes(presentation) : presentation;
9669
+ return verifyPresentation(decodedPresentation, query, options);
9359
9670
  }
9360
9671
 
9361
9672
  // src/index.ts
@@ -10055,6 +10366,8 @@ exports.SdJwtParser = SdJwtParser;
10055
10366
  exports.StaticTrustStore = StaticTrustStore;
10056
10367
  exports.VERSION = VERSION;
10057
10368
  exports.buildHaipQuery = buildHaipQuery;
10369
+ exports.buildOid4vpSessionTranscript = buildOid4vpSessionTranscript;
10370
+ exports.buildOpenID4VPHandoverSessionTranscript = buildOpenID4VPHandoverSessionTranscript;
10058
10371
  exports.createAuthorizationRequest = createAuthorizationRequest;
10059
10372
  exports.createSignedAuthorizationRequest = createSignedAuthorizationRequest;
10060
10373
  exports.decryptAuthorizationResponse = decryptAuthorizationResponse;