{"version":3,"file":"credentialTransformer.mjs","names":[],"sources":["../../../../src/modules/vc/jwt-vc/credentialTransformer.ts"],"sourcesContent":["import { isObject } from 'class-validator'\nimport type { JwtPayloadOptions } from '../../../crypto/jose/jwt'\n\nimport { JwtPayload } from '../../../crypto/jose/jwt'\nimport { CredoError } from '../../../error'\nimport { isJsonObject } from '../../../types'\nimport { JsonTransformer } from '../../../utils'\nimport { W3cCredential } from '../models/credential/W3cCredential'\nimport { w3cDate } from '../util'\n\nexport function getJwtPayloadFromCredential(credential: W3cCredential) {\n  const vc = JsonTransformer.toJSON(credential)\n\n  const payloadOptions: JwtPayloadOptions = {\n    additionalClaims: {\n      vc,\n    },\n  }\n\n  // Extract `nbf` and remove issuance date from vc\n  const issuanceDate = Date.parse(credential.issuanceDate)\n  if (Number.isNaN(issuanceDate)) {\n    throw new CredoError('JWT VCs must have a valid issuance date')\n  }\n  payloadOptions.nbf = Math.floor(issuanceDate / 1000)\n  // biome-ignore lint/performance/noDelete: no explanation\n  delete vc.issuanceDate\n\n  // Extract `exp` and remove expiration date from vc\n  if (credential.expirationDate) {\n    const expirationDate = Date.parse(credential.expirationDate)\n    if (!Number.isNaN(expirationDate)) {\n      payloadOptions.exp = Math.floor(expirationDate / 1000)\n      // biome-ignore lint/performance/noDelete: no explanation\n      delete vc.expirationDate\n    }\n  }\n\n  // Extract `iss` and remove issuer id from vc\n  payloadOptions.iss = credential.issuerId\n  if (typeof vc.issuer === 'string') {\n    // biome-ignore lint/performance/noDelete: no explanation\n    delete vc.issuer\n  } else if (typeof vc.issuer === 'object') {\n    // biome-ignore lint/performance/noDelete: no explanation\n    delete vc.issuer.id\n    if (Object.keys(vc.issuer).length === 0) {\n      // biome-ignore lint/performance/noDelete: no explanation\n      delete vc.issuer\n    }\n  }\n\n  // Extract `jti` and remove id from vc\n  if (credential.id) {\n    payloadOptions.jti = credential.id\n    // biome-ignore lint/performance/noDelete: no explanation\n    delete vc.id\n  }\n\n  if (Array.isArray(credential.credentialSubject) && credential.credentialSubject.length !== 1) {\n    throw new CredoError('JWT VCs must have exactly one credential subject')\n  }\n\n  // Extract `sub` and remove credential subject id from vc\n  const [credentialSubjectId] = credential.credentialSubjectIds\n  if (credentialSubjectId) {\n    payloadOptions.sub = credentialSubjectId\n\n    if (Array.isArray(vc.credentialSubject)) {\n      // biome-ignore lint/performance/noDelete: no explanation\n      delete vc.credentialSubject[0].id\n    } else {\n      // biome-ignore lint/performance/noDelete: no explanation\n      delete vc.credentialSubject?.id\n    }\n  }\n\n  return new JwtPayload(payloadOptions)\n}\n\nexport function getCredentialFromJwtPayload(jwtPayload: JwtPayload) {\n  if (!('vc' in jwtPayload.additionalClaims) || !isJsonObject(jwtPayload.additionalClaims.vc)) {\n    throw new CredoError(\"JWT does not contain a valid 'vc' claim\")\n  }\n\n  const jwtVc = jwtPayload.additionalClaims.vc\n\n  if (!jwtPayload.nbf || !jwtPayload.iss) {\n    throw new CredoError(\"JWT does not contain valid 'nbf' and 'iss' claims\")\n  }\n\n  if (Array.isArray(jwtVc.credentialSubject) && jwtVc.credentialSubject.length !== 1) {\n    throw new CredoError('JWT VCs must have exactly one credential subject')\n  }\n\n  if (Array.isArray(jwtVc.credentialSubject) && !isObject(jwtVc.credentialSubject[0])) {\n    throw new CredoError('JWT VCs must have a credential subject of type object')\n  }\n\n  const credentialSubject = Array.isArray(jwtVc.credentialSubject)\n    ? jwtVc.credentialSubject[0]\n    : jwtVc.credentialSubject\n  if (!isJsonObject(credentialSubject)) {\n    throw new CredoError('JWT VC does not have a valid credential subject')\n  }\n  const subjectWithId = jwtPayload.sub ? { ...credentialSubject, id: jwtPayload.sub } : credentialSubject\n\n  // Validate vc.id and jti\n  if (jwtVc.id && jwtPayload.jti !== jwtVc.id) {\n    throw new CredoError('JWT jti and vc.id do not match')\n  }\n\n  // Validate vc.issuer and iss\n  if (\n    (typeof jwtVc.issuer === 'string' && jwtPayload.iss !== jwtVc.issuer) ||\n    (isJsonObject(jwtVc.issuer) && jwtVc.issuer.id && jwtPayload.iss !== jwtVc.issuer.id)\n  ) {\n    throw new CredoError('JWT iss and vc.issuer(.id) do not match')\n  }\n\n  // Validate vc.issuanceDate and nbf\n  if (jwtVc.issuanceDate) {\n    if (typeof jwtVc.issuanceDate !== 'string') {\n      throw new CredoError('JWT vc.issuanceDate must be a string')\n    }\n\n    const issuanceDate = Date.parse(jwtVc.issuanceDate) / 1000\n    if (jwtPayload.nbf !== issuanceDate) {\n      throw new CredoError('JWT nbf and vc.issuanceDate do not match')\n    }\n  }\n\n  // Validate vc.expirationDate and exp\n  if (jwtVc.expirationDate) {\n    if (typeof jwtVc.expirationDate !== 'string') {\n      throw new CredoError('JWT vc.expirationDate must be a string')\n    }\n\n    const expirationDate = Date.parse(jwtVc.expirationDate) / 1000\n    if (expirationDate !== jwtPayload.exp) {\n      throw new CredoError('JWT exp and vc.expirationDate do not match')\n    }\n  }\n\n  // Validate vc.credentialSubject.id and sub\n  if (\n    (isJsonObject(jwtVc.credentialSubject) &&\n      jwtVc.credentialSubject.id &&\n      jwtPayload.sub !== jwtVc.credentialSubject.id) ||\n    (Array.isArray(jwtVc.credentialSubject) &&\n      isJsonObject(jwtVc.credentialSubject[0]) &&\n      jwtVc.credentialSubject[0].id &&\n      jwtPayload.sub !== jwtVc.credentialSubject[0].id)\n  ) {\n    throw new CredoError('JWT sub and vc.credentialSubject.id do not match')\n  }\n\n  // Create a verifiable credential structure that is compatible with the VC data model\n  const dataModelVc = {\n    ...jwtVc,\n    issuanceDate: w3cDate(jwtPayload.nbf * 1000),\n    expirationDate: jwtPayload.exp ? w3cDate(jwtPayload.exp * 1000) : undefined,\n    issuer: typeof jwtVc.issuer === 'object' ? { ...jwtVc.issuer, id: jwtPayload.iss } : jwtPayload.iss,\n    id: jwtPayload.jti,\n    credentialSubject: Array.isArray(jwtVc.credentialSubject) ? [subjectWithId] : subjectWithId,\n  }\n\n  const vcInstance = JsonTransformer.fromJSON(dataModelVc, W3cCredential)\n\n  return vcInstance\n}\n"],"mappings":"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"}