UNPKG

@credo-ts/core

Version:

<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1

1 lines • 8.93 kB
{"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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"}