@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 • 13.1 kB
Source Map (JSON)
{"version":3,"file":"v2-jwt-utils.mjs","names":[],"sources":["../../../src/modules/vc/v2-jwt-utils.ts"],"sourcesContent":["import { AgentContext } from '../../agent'\nimport { CredoError } from '../../error'\nimport { asArray, isDid } from '../../utils'\nimport {\n type DidPurpose,\n DidResolverService,\n DidsApi,\n getPublicJwkFromVerificationMethod,\n parseDid,\n VerificationMethod,\n} from '../dids'\nimport { getSupportedVerificationMethodTypesForPublicJwk } from '../dids/domain/key-type/keyDidMapping'\nimport { type KnownJwaSignatureAlgorithm, PublicJwk } from '../kms'\nimport { extractKeyFromHolderBinding, parseHolderBindingFromCredential } from '../sd-jwt-vc/utils'\nimport { W3cV2JwtVerifiableCredential } from './jwt-vc/W3cV2JwtVerifiableCredential'\nimport { W3cV2JwtVerifiablePresentation } from './jwt-vc/W3cV2JwtVerifiablePresentation'\nimport { W3cV2EnvelopedVerifiableCredential } from './models/credential/W3cV2EnvelopedVerifiableCredential'\nimport type { W3cV2Presentation } from './models/presentation/W3cV2Presentation'\nimport { W3cV2SdJwtVerifiableCredential } from './sd-jwt-vc/W3cV2SdJwtVerifiableCredential'\nimport { W3cV2SdJwtVerifiablePresentation } from './sd-jwt-vc/W3cV2SdJwtVerifiablePresentation'\n\nexport async function validateAndResolveVerificationMethod(\n agentContext: AgentContext,\n verificationMethod: string,\n allowsPurposes?: DidPurpose[]\n) {\n if (!isDid(verificationMethod)) {\n throw new CredoError('Only did identifiers are supported as verification method')\n }\n\n const parsedDid = parseDid(verificationMethod)\n if (!parsedDid.fragment) {\n throw new CredoError(`didUrl '${parsedDid.didUrl}' does not contain a '#'. Unable to derive key from did document`)\n }\n\n const dids = agentContext.resolve(DidsApi)\n const { didDocument, keys } = await dids.resolveCreatedDidDocumentWithKeys(parsedDid.did)\n const verificationMethodObject = didDocument.dereferenceKey(verificationMethod, allowsPurposes)\n const publicJwk = getPublicJwkFromVerificationMethod(verificationMethodObject)\n\n publicJwk.keyId =\n keys?.find(({ didDocumentRelativeKeyId }) => verificationMethodObject.id.endsWith(didDocumentRelativeKeyId))\n ?.kmsKeyId ?? publicJwk.legacyKeyId\n\n return publicJwk\n}\n\nexport async function extractHolderFromPresentationCredentials(\n agentContext: AgentContext,\n presentation: W3cV2Presentation\n) {\n const credentials = asArray(presentation.verifiableCredential)\n\n const holderDid = presentation.holderId\n if (holderDid) {\n if (!isDid(holderDid)) {\n throw new CredoError(`Presentation holder '${holderDid}' is not a valid did`)\n }\n\n const dids = agentContext.resolve(DidsApi)\n const { didDocument, keys } = await dids.resolveCreatedDidDocumentWithKeys(holderDid)\n\n const authenticationMethods = didDocument.findVerificationMethodsByPurpose(['authentication'])\n\n const candidateMethods = authenticationMethods.filter((method) =>\n keys?.some(({ didDocumentRelativeKeyId }) => method.id.endsWith(didDocumentRelativeKeyId))\n )\n\n if (candidateMethods.length === 0) {\n throw new CredoError(\n `Unable to determine signer key for presentation holder '${holderDid}'. No locally controlled authentication verification method found.`\n )\n }\n\n if (candidateMethods.length > 1) {\n throw new CredoError(\n `Unable to deterministically resolve signer key for presentation holder '${holderDid}'. Multiple locally controlled authentication verification methods found.`\n )\n }\n\n const selectedMethod = candidateMethods[0]\n const publicJwk = getPublicJwkFromVerificationMethod(selectedMethod)\n publicJwk.keyId =\n keys?.find(({ didDocumentRelativeKeyId }) => selectedMethod.id.endsWith(didDocumentRelativeKeyId))?.kmsKeyId ??\n publicJwk.legacyKeyId\n\n const [alg] = publicJwk.supportedSignatureAlgorithms\n if (!alg) {\n throw new CredoError(\n `No supported JWA signature algorithms found for holder verification method '${selectedMethod.id}'`\n )\n }\n\n return {\n alg,\n publicJwk,\n cnf: {\n kid: selectedMethod.id,\n },\n }\n }\n\n const fallbackHolders: Array<Awaited<ReturnType<typeof extractKeyFromHolderBinding>>> = []\n\n for (const credential of credentials) {\n if (!(credential instanceof W3cV2EnvelopedVerifiableCredential)) continue\n\n let claims: Record<string, unknown>\n if (credential.envelopedCredential instanceof W3cV2SdJwtVerifiableCredential) {\n claims = credential.envelopedCredential.sdJwt.prettyClaims\n } else if (credential.envelopedCredential instanceof W3cV2JwtVerifiableCredential) {\n claims = credential.envelopedCredential.jwt.payload.toJson()\n } else {\n continue\n }\n\n const holderBinding = parseHolderBindingFromCredential(claims)\n if (!holderBinding) continue\n\n fallbackHolders.push(await extractKeyFromHolderBinding(agentContext, holderBinding, { forSigning: true }))\n }\n\n if (fallbackHolders.length === 0) {\n throw new CredoError('Unable to determine signer from presentation credentials, and presentation.holder is missing')\n }\n\n const uniqueFallbackHolders = new Map(fallbackHolders.map((holder) => [holder.publicJwk.fingerprint, holder]))\n if (uniqueFallbackHolders.size > 1) {\n throw new CredoError(\n 'Unable to determine signer from presentation credentials. Multiple distinct holder bindings found and presentation.holder is missing.'\n )\n }\n\n return uniqueFallbackHolders.values().next().value as Awaited<ReturnType<typeof extractKeyFromHolderBinding>>\n}\n\n/**\n * This method tries to find the verification method associated with the JWT credential or presentation.\n * This verification method can then be used to verify the credential or presentation signature.\n */\nexport async function getVerificationMethodForJwt(\n agentContext: AgentContext,\n credential:\n | W3cV2JwtVerifiableCredential\n | W3cV2JwtVerifiablePresentation\n | W3cV2SdJwtVerifiableCredential\n | W3cV2SdJwtVerifiablePresentation,\n purpose?: DidPurpose[]\n) {\n let alg: KnownJwaSignatureAlgorithm\n let kid: string | undefined\n let iss: string | undefined\n\n // Determine the algorithm, kid and iss based on the type of credential / presentation\n if (credential instanceof W3cV2JwtVerifiableCredential) {\n alg = credential.jwt.header.alg as KnownJwaSignatureAlgorithm\n kid = credential.jwt.header.kid\n iss = credential.jwt.payload.iss ?? credential.resolvedCredential.issuerId\n } else if (credential instanceof W3cV2JwtVerifiablePresentation) {\n alg = credential.jwt.header.alg as KnownJwaSignatureAlgorithm\n kid = credential.jwt.header.kid\n iss = credential.jwt.payload.iss ?? credential.resolvedPresentation.holderId\n } else if (credential instanceof W3cV2SdJwtVerifiableCredential) {\n alg = credential.sdJwt.header.alg as KnownJwaSignatureAlgorithm\n kid = credential.sdJwt.header.kid\n iss = credential.sdJwt.payload.iss ?? credential.resolvedCredential.issuerId\n } else {\n alg = credential.sdJwt.header.alg as KnownJwaSignatureAlgorithm\n kid = credential.sdJwt.header.kid\n iss = credential.sdJwt.payload.iss ?? credential.resolvedPresentation.holderId\n }\n\n const didResolver = agentContext.dependencyManager.resolve(DidResolverService)\n let verificationMethod: VerificationMethod\n\n // If the kid starts with # we assume it is a relative did url, and we resolve\n //it based on the `iss` and the `kid`\n if (kid?.startsWith('#')) {\n if (!iss || !isDid(iss)) {\n throw new CredoError(`JWT 'iss' MUST be a did when 'kid' is a relative did url`)\n }\n\n const didDocument = await didResolver.resolveDidDocument(agentContext, iss)\n verificationMethod = didDocument.dereferenceKey(`${iss}${kid}`, purpose)\n } else if (kid && isDid(kid)) {\n const didDocument = await didResolver.resolveDidDocument(agentContext, kid)\n verificationMethod = didDocument.dereferenceKey(kid, purpose)\n\n if (iss && didDocument.id !== iss) {\n throw new CredoError(`kid '${kid}' does not match id of signer (holder/issuer) '${iss}'`)\n }\n } else {\n if (!iss) {\n throw new CredoError(`JWT 'iss' MUST be present in payload when no 'kid' is specified`)\n }\n\n // Find the verificationMethod in the did document based on the alg and proofPurpose\n const jwkClass = PublicJwk.supportedPublicJwkClassForSignatureAlgorithm(alg)\n const supportedVerificationMethodTypes = getSupportedVerificationMethodTypesForPublicJwk(jwkClass)\n\n const didDocument = await didResolver.resolveDidDocument(agentContext, iss)\n const verificationMethods = didDocument.findVerificationMethodsByTypeAndPurpose(supportedVerificationMethodTypes, [\n 'assertionMethod',\n ])\n\n if (verificationMethods.length === 0) {\n throw new CredoError(\n `No verification methods found for signer '${iss}' and key type '${jwkClass.name}' for alg '${alg}'. Unable to determine which public key is associated with the credential.`\n )\n }\n if (verificationMethods.length > 1) {\n throw new CredoError(\n `Multiple verification methods found for signer '${iss}' and key type '${jwkClass.name}' for alg '${alg}'. Unable to determine which public key is associated with the credential.`\n )\n }\n\n verificationMethod = verificationMethods[0]\n }\n\n // Verify the controller of the verificationMethod matches the signer of the credential\n if (iss && verificationMethod.controller !== iss) {\n throw new CredoError(\n `Verification method controller '${verificationMethod.controller}' does not match the signer '${iss}'`\n )\n }\n\n return verificationMethod\n}\n"],"mappings":"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"}