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.99 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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"}