{"version":3,"file":"MdocDeviceResponse.mjs","names":[],"sources":["../../../src/modules/mdoc/MdocDeviceResponse.ts"],"sourcesContent":["import {\n  CoseKey,\n  DeviceRequest,\n  DeviceResponse,\n  DocRequest,\n  Document,\n  defaultVerificationCallback,\n  Holder,\n  ItemsRequest,\n  type MdocContext,\n  SessionTranscript,\n} from '@owf/mdoc'\nimport type { InputDescriptorV2 } from '@sphereon/pex-models'\nimport {\n  convertDcqlQueryToDeviceRequest,\n  convertPresentationDefinitionToDeviceRequest,\n  type Field,\n  type PresentationDefinition,\n} from '@verifiables/request-converter'\nimport { AgentContext } from '../../agent'\nimport { getMdocContext } from '../../crypto/contexts/mdocContext'\nimport { TypedArrayEncoder } from './../../utils'\nimport { PublicJwk } from '../kms'\nimport { ClaimFormat } from '../vc'\nimport type { Mdoc } from './Mdoc'\nimport { MdocError } from './MdocError'\nimport type {\n  MdocDeviceResponseDcqlQueryOptions,\n  MdocDeviceResponseOptions,\n  MdocDeviceResponsePresentationDefinitionOptions,\n  MdocDeviceResponseVerifyOptions,\n  MdocSessionTranscriptOptions,\n} from './MdocOptions'\nimport { isMdocSupportedSignatureAlgorithm, mdocSupportedSignatureAlgorithms } from './mdocSupportedAlgs'\nimport {\n  assertMdocStatusListChainsMatchIssuanceChain,\n  convertMdocTrustedCertificates,\n  mdocTrustedCertificatesToRaw,\n  nameSpacesRecordToDeviceNamespaces,\n  nameSpacesRecordToMap,\n} from './mdocUtil'\nimport { convertDocumentRequest } from './utils/convertDocumentRequest'\n\nexport type DeviceAndIssuerClaims = {\n  [docType: string]: {\n    [namespace: string]: {\n      [claimIdentifier: string]: unknown\n    }\n  }\n}\n\nexport class MdocDeviceResponse {\n  private constructor(public readonly deviceResponse: DeviceResponse) {}\n\n  /**\n   * claim format is convenience method added to all credential instances\n   */\n  public get claimFormat() {\n    return ClaimFormat.MsoMdoc as const\n  }\n\n  /**\n   * Encoded is convenience method added to all credential instances\n   */\n  public get encoded() {\n    return TypedArrayEncoder.toBase64Url(this.deviceResponse.encode())\n  }\n\n  /**\n   * To support a single DeviceResponse with multiple documents in OpenID4VP\n   */\n  public splitIntoSingleDocumentResponses(): MdocDeviceResponse[] {\n    const deviceResponses: MdocDeviceResponse[] = []\n\n    if (!this.deviceResponse.documents || this.deviceResponse.documents.length === 0) {\n      throw new MdocError('mdoc device response does not contain any mdocs')\n    }\n\n    for (const document of this.deviceResponse.documents) {\n      deviceResponses.push(\n        new MdocDeviceResponse(\n          DeviceResponse.createSimple({\n            version: this.deviceResponse.version,\n            status: this.deviceResponse.status,\n            documentErrors: this.deviceResponse.documentErrors,\n            documents: [document],\n          })\n        )\n      )\n    }\n\n    return deviceResponses\n  }\n\n  public static fromBase64Url(base64Url: string) {\n    const parsed = DeviceResponse.decode(TypedArrayEncoder.fromBase64Url(base64Url))\n\n    return new MdocDeviceResponse(parsed)\n  }\n\n  public static async createDeviceResponseWithPresentationDefinition(\n    agentContext: AgentContext,\n    options: MdocDeviceResponsePresentationDefinitionOptions\n  ) {\n    // @ts-expect-error: we need to match the types credo uses and the converter expects\n    const { deviceRequest } = convertPresentationDefinitionToDeviceRequest(options.presentationDefinition)\n    const documentRequests = convertDocumentRequest(deviceRequest.docRequests)\n\n    return MdocDeviceResponse.createDeviceResponse(agentContext, { ...options, documentRequests })\n  }\n\n  /**\n   * @deprecated Credo does not use this method itself, and it only supports part of DCQL. Every claim\n   * of every `mso_mdoc` credential query is requested: `credential_sets`, `claim_sets` and `values`\n   * are ignored, credential queries with the same doctype are merged, nested claim paths are\n   * truncated, and a claim missing from the mdoc throws instead of being treated as optional. Use\n   * `DcqlService.createPresentation` to present mdocs for a DCQL query, or\n   * {@link MdocDeviceResponse.createDeviceResponse} with explicit `documentRequests`.\n   */\n  public static async createDeviceResponseWithDcqlQuery(\n    agentContext: AgentContext,\n    options: MdocDeviceResponseDcqlQueryOptions\n  ) {\n    // @ts-expect-error: we need to match the types credo uses and the converter expects\n    const { deviceRequest } = convertDcqlQueryToDeviceRequest(options.dcqlQuery)\n    const documentRequests = convertDocumentRequest(deviceRequest.docRequests)\n\n    return MdocDeviceResponse.createDeviceResponse(agentContext, { ...options, documentRequests })\n  }\n\n  public static async limitDisclosureToInputDescriptor(\n    _agentContext: AgentContext,\n    { mdoc, ...options }: { inputDescriptor: InputDescriptorV2; mdoc: Mdoc }\n  ) {\n    const inputDescriptor = MdocDeviceResponse.assertMdocInputDescriptor(options.inputDescriptor)\n\n    // First we try with all optional fields enabled, if the mdoc cannot satisfy that request, we try again, skipping all optional fields\n    const docRequestMatch =\n      MdocDeviceResponse.matchInputDescriptor(mdoc, inputDescriptor, { skipOptionalFields: false }) ??\n      MdocDeviceResponse.matchInputDescriptor(mdoc, inputDescriptor, { skipOptionalFields: true })\n\n    if (!docRequestMatch) {\n      throw new MdocError(`Mdoc with doctype ${mdoc.docType} does not satisfy the input descriptor`)\n    }\n\n    const disclosedPayloadAsRecord: Record<string, Record<string, unknown>> = {}\n    for (const claim of docRequestMatch.claims.validClaims) {\n      disclosedPayloadAsRecord[claim.namespace] ??= {}\n      disclosedPayloadAsRecord[claim.namespace][claim.disclosedElementIdentifier] = claim.elementValue\n    }\n\n    return disclosedPayloadAsRecord\n  }\n\n  private static matchInputDescriptor(\n    mdoc: Mdoc,\n    inputDescriptor: PresentationDefinition['input_descriptors'][number],\n    { skipOptionalFields }: { skipOptionalFields: boolean }\n  ) {\n    // We take the first document request as we also only input a single input descriptor\n    const {\n      deviceRequest: {\n        docRequests: [convertedDocumentRequest],\n      },\n    } = convertPresentationDefinitionToDeviceRequest(\n      {\n        id: '<UNUSED_CREDO_ID>',\n        input_descriptors: [inputDescriptor],\n      },\n      { skipOptionalFields }\n    )\n\n    const { docRequests } = Holder.matchDeviceRequest({\n      deviceRequest: DeviceRequest.create({\n        version: '1.0',\n        docRequests: [\n          DocRequest.create({\n            itemsRequest: ItemsRequest.create({\n              docType: convertedDocumentRequest.itemsRequest.docType,\n              namespaces: convertedDocumentRequest.itemsRequest.nameSpaces,\n            }),\n          }),\n        ],\n      }),\n      credentials: [mdoc.issuerSigned],\n    })\n\n    return docRequests[0].success ? docRequests[0].validCredentials[0] : undefined\n  }\n\n  private static assertMdocInputDescriptor(inputDescriptor: InputDescriptorV2) {\n    if (!inputDescriptor.format?.mso_mdoc) {\n      throw new MdocError(`Input descriptor must contain 'mso_mdoc' format property`)\n    }\n\n    if (!inputDescriptor.format.mso_mdoc.alg) {\n      throw new MdocError(`Input descriptor mso_mdoc must contain 'alg' property`)\n    }\n\n    if (!inputDescriptor.constraints?.limit_disclosure || inputDescriptor.constraints.limit_disclosure !== 'required') {\n      throw new MdocError(\n        `Input descriptor must contain 'limit_disclosure' constraints property which is set to required`\n      )\n    }\n\n    if (!inputDescriptor.constraints?.fields?.every((field) => field.intent_to_retain !== undefined)) {\n      throw new MdocError(`Input descriptor must contain 'intent_to_retain' constraints property`)\n    }\n\n    return {\n      ...inputDescriptor,\n      format: {\n        mso_mdoc: inputDescriptor.format.mso_mdoc,\n      },\n      constraints: {\n        ...inputDescriptor.constraints,\n        limit_disclosure: 'required',\n        fields: (inputDescriptor.constraints.fields ?? []).map((field) => {\n          return {\n            ...field,\n            intent_to_retain: field.intent_to_retain ?? false,\n          }\n        }) as Field[],\n      },\n    } satisfies PresentationDefinition['input_descriptors'][number]\n  }\n\n  public static async createDeviceResponse(agentContext: AgentContext, options: MdocDeviceResponseOptions) {\n    const documents: Document[] = []\n\n    for (const document of options.mdocs) {\n      const deviceKeyJwk = document.deviceKey\n      const deviceKeyJwkJson = deviceKeyJwk.toJson()\n\n      if (!deviceKeyJwkJson.alg) {\n        // FIXME: we cannot provide alg anymore?\n        deviceKeyJwkJson.alg = MdocDeviceResponse.getAlgForDeviceKeyJwk(deviceKeyJwk)\n      }\n\n      // Set keyId to legacy key id if it doesn't have a key id set\n      if (!deviceKeyJwk.hasKeyId) {\n        deviceKeyJwk.keyId = deviceKeyJwk.legacyKeyId\n      }\n\n      const deviceRequestForDocument = DeviceRequest.create({\n        version: '1.0',\n        docRequests: options.documentRequests\n          .filter((request) => request.docType === document.docType)\n          .map((request) =>\n            DocRequest.create({\n              itemsRequest: ItemsRequest.create({\n                docType: request.docType,\n                namespaces: nameSpacesRecordToMap(request.nameSpaces),\n              }),\n            })\n          ),\n      })\n\n      const mdocContext = getMdocContext(agentContext)\n      const deviceResponse = await DeviceResponse.createWithDeviceRequest(\n        {\n          deviceRequest: deviceRequestForDocument,\n          sessionTranscript: await MdocDeviceResponse.calculateSessionTranscriptBytes(\n            mdocContext,\n            options.sessionTranscriptOptions\n          ),\n          documents: [\n            {\n              issuerSigned: document.issuerSigned,\n              // `deviceRequestForDocument` only holds doc requests for this document's doc type, and\n              // only the first disclosed document is kept below, so answer the first one.\n              docRequestIndex: 0,\n              deviceNamespaces: options.deviceNameSpaces\n                ? nameSpacesRecordToDeviceNamespaces(options.deviceNameSpaces)\n                : undefined,\n              signature: {\n                signingKey: CoseKey.fromJwk(deviceKeyJwk.toJson()),\n              },\n            },\n          ],\n        },\n        mdocContext\n      )\n\n      if (!deviceResponse.documents) {\n        throw new MdocError('Device response does not contain any documents')\n      }\n      documents.push(deviceResponse.documents[0])\n    }\n\n    return new MdocDeviceResponse(\n      DeviceResponse.createSimple({\n        version: '1.0',\n        documents,\n      })\n    )\n  }\n\n  public async verify(agentContext: AgentContext, options: Omit<MdocDeviceResponseVerifyOptions, 'deviceResponse'>) {\n    const mdocContext = getMdocContext(agentContext)\n\n    defaultVerificationCallback({\n      status: this.deviceResponse.documents?.length ? 'PASSED' : 'FAILED',\n      check: 'Device Response must include at least one document.',\n      category: 'DOCUMENT_FORMAT',\n    })\n\n    const trustedCertificates = convertMdocTrustedCertificates(options.trustedCertificates ?? [])\n\n    const { documents: verificationResults } = await this.deviceResponse\n      .verify(\n        {\n          trustedCertificates: mdocTrustedCertificatesToRaw(trustedCertificates),\n          disableCertificateChainValidation: false,\n          now: options.now,\n          skewSeconds: agentContext.config.validitySkewSeconds,\n          sessionTranscript: await MdocDeviceResponse.calculateSessionTranscriptBytes(\n            mdocContext,\n            options.sessionTranscriptOptions\n          ),\n        },\n        mdocContext\n      )\n      .catch((error) => {\n        throw new MdocError(`Mdoc with doctype ${this.deviceResponse.documents?.[0].docType} is not valid`, {\n          cause: error,\n        })\n      })\n\n    for (const { trustedIssuanceChain, trustedStatusListChain, trustedIdentifierListChain } of verificationResults) {\n      if (!trustedIssuanceChain) continue\n\n      assertMdocStatusListChainsMatchIssuanceChain(trustedCertificates, {\n        trustedIssuanceChain,\n        trustedStatusListChain,\n        trustedIdentifierListChain,\n      })\n    }\n  }\n\n  private static async calculateSessionTranscriptBytes(\n    mdocContext: MdocContext,\n    options: MdocSessionTranscriptOptions\n  ) {\n    if (options.type === 'sessionTranscriptBytes') {\n      return options.sessionTranscriptBytes\n    }\n\n    if (options.type === 'openId4VpDraft18') {\n      return await SessionTranscript.forOid4VpDraft18(options, mdocContext)\n    }\n\n    if (options.type === 'openId4Vp') {\n      const { encryptionJwk, verifierGeneratedNonce, ...rest } = options\n      return await SessionTranscript.forOid4Vp(\n        {\n          ...rest,\n          jwkThumbprint: encryptionJwk ? encryptionJwk.getJwkThumbprint() : undefined,\n          nonce: verifierGeneratedNonce,\n        },\n        mdocContext\n      )\n    }\n\n    if (options.type === 'openId4VpDcApi') {\n      const { encryptionJwk, verifierGeneratedNonce, ...rest } = options\n      return await SessionTranscript.forOid4VpDcApi(\n        {\n          ...rest,\n          nonce: verifierGeneratedNonce,\n          jwkThumbprint: encryptionJwk ? encryptionJwk.getJwkThumbprint() : undefined,\n        },\n        mdocContext\n      )\n    }\n\n    if (options.type === 'openId4VpDcApiDraft24') {\n      const { verifierGeneratedNonce, ...rest } = options\n\n      return await SessionTranscript.forOid4VpDcApiDraft24(\n        {\n          ...rest,\n          nonce: verifierGeneratedNonce,\n        },\n        mdocContext\n      )\n    }\n\n    throw new MdocError('Unsupported session transcript option')\n  }\n\n  private static getAlgForDeviceKeyJwk(jwk: PublicJwk) {\n    const signatureAlgorithm = jwk.supportedSignatureAlgorithms.find(isMdocSupportedSignatureAlgorithm)\n    if (!signatureAlgorithm) {\n      throw new MdocError(\n        `Unable to create mdoc device response. No supported signature algorithm found to sign device response for jwk  ${\n          jwk.jwkTypeHumanDescription\n        }. Key supports algs ${jwk.supportedSignatureAlgorithms.join(\n          ', '\n        )}. mdoc supports algs ${mdocSupportedSignatureAlgorithms.join(', ')}`\n      )\n    }\n\n    return signatureAlgorithm\n  }\n\n  public get issuerClaims(): DeviceAndIssuerClaims {\n    if (!this.deviceResponse.documents) return {}\n\n    return this.deviceResponse.documents.reduce(\n      (prev, document) => ({\n        // biome-ignore lint/performance/noAccumulatingSpread: time complexity is not relevant here\n        ...prev,\n        [document.docType]: Object.fromEntries(\n          Array.from(document.issuerSigned.issuerNamespaces?.issuerNamespaces.entries() ?? []).map(\n            ([namespace, claim]) => [\n              namespace,\n              Object.fromEntries(claim.map((c) => [c.elementIdentifier, c.elementValue])),\n            ]\n          )\n        ),\n      }),\n      {}\n    )\n  }\n\n  public get deviceClaims(): DeviceAndIssuerClaims {\n    if (!this.deviceResponse.documents) return {}\n\n    return this.deviceResponse.documents.reduce(\n      (prev, document) => ({\n        // biome-ignore lint/performance/noAccumulatingSpread: time complexity is not relevant here\n        ...prev,\n        [document.docType]: Object.fromEntries(\n          Array.from(document.deviceSigned.deviceNamespaces.deviceNamespaces.entries()).map(([namespace, claim]) => [\n            namespace,\n            Object.fromEntries(claim.deviceSignedItems),\n          ])\n        ),\n      }),\n      {}\n    )\n  }\n}\n"],"mappings":"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"}