@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 • 28.3 kB
Source Map (JSON)
{"version":3,"file":"W3cJwtCredentialService.mjs","names":[],"sources":["../../../../src/modules/vc/jwt-vc/W3cJwtCredentialService.ts"],"sourcesContent":["import type { AgentContext } from '../../../agent/context'\nimport { TrustedIssuerContext } from '../../../agent/TrustedIssuerContext'\nimport type { VerifyJwsResult } from '../../../crypto/JwsService'\nimport { JwsService } from '../../../crypto/JwsService'\nimport { CredoError } from '../../../error'\nimport { injectable } from '../../../plugins'\nimport { asArray, isDid, MessageValidator } from '../../../utils'\nimport type { DidPurpose, VerificationMethod } from '../../dids'\nimport { DidResolverService, DidsApi, parseDid } from '../../dids'\nimport {\n getPublicJwkFromVerificationMethod,\n getSupportedVerificationMethodTypesForPublicJwk,\n} from '../../dids/domain/key-type/keyDidMapping'\nimport { type KnownJwaSignatureAlgorithm, PublicJwk } from '../../kms'\nimport { W3cJsonLdVerifiableCredential } from '../linked-data-proofs/models/W3cJsonLdVerifiableCredential'\nimport type { W3cVerifyCredentialResult, W3cVerifyPresentationResult } from '../models'\nimport { validateCredentialSubjectAuthentication } from '../util'\nimport type {\n W3cJwtSignCredentialOptions,\n W3cJwtSignPresentationOptions,\n W3cJwtVerifyCredentialOptions,\n W3cJwtVerifyPresentationOptions,\n} from '../W3cCredentialServiceOptions'\nimport { getJwtPayloadFromCredential } from './credentialTransformer'\nimport { getJwtPayloadFromPresentation } from './presentationTransformer'\nimport { W3cJwtVerifiableCredential } from './W3cJwtVerifiableCredential'\nimport { W3cJwtVerifiablePresentation } from './W3cJwtVerifiablePresentation'\n\n/**\n * Supports signing and verification of credentials according to the [Verifiable Credential Data Model](https://www.w3.org/TR/vc-data-model)\n * using [Json Web Tokens](https://www.w3.org/TR/vc-data-model/#json-web-token).\n */\n@injectable()\nexport class W3cJwtCredentialService {\n private jwsService: JwsService\n\n public constructor(jwsService: JwsService) {\n this.jwsService = jwsService\n }\n\n /**\n * Signs a credential\n */\n public async signCredential(\n agentContext: AgentContext,\n options: W3cJwtSignCredentialOptions\n ): Promise<W3cJwtVerifiableCredential> {\n // Validate the instance\n MessageValidator.validateSync(options.credential)\n\n // Get the JWT payload for the JWT based on the JWT Encoding rules form the VC-DATA-MODEL\n // https://www.w3.org/TR/vc-data-model/#jwt-encoding\n const jwtPayload = getJwtPayloadFromCredential(options.credential)\n\n if (!isDid(options.verificationMethod)) {\n throw new CredoError('Only did identifiers are supported as verification method')\n }\n\n const publicJwk = await this.resolveVerificationMethod(agentContext, options.verificationMethod, [\n 'assertionMethod',\n ])\n\n const jwt = await this.jwsService.createJwsCompact(agentContext, {\n payload: jwtPayload,\n keyId: publicJwk.keyId,\n protectedHeaderOptions: {\n typ: 'JWT',\n alg: options.alg,\n kid: options.verificationMethod,\n },\n })\n\n // TODO: this re-parses and validates the credential in the JWT, which is not necessary.\n // We should somehow create an instance of W3cJwtVerifiableCredential directly from the JWT\n const jwtVc = W3cJwtVerifiableCredential.fromSerializedJwt(jwt)\n\n return jwtVc\n }\n\n /**\n * Verifies the signature(s) of a credential\n *\n * @param credential the credential to be verified\n * @returns the verification result\n */\n public async verifyCredential(\n agentContext: AgentContext,\n options: W3cJwtVerifyCredentialOptions\n ): Promise<W3cVerifyCredentialResult> {\n // NOTE: this is mostly from the JSON-LD service that adds this option. Once we support\n // the same granular validation results, we can remove this and the user could just check\n // which of the validations failed. Supporting for consistency with the JSON-LD service for now.\n const verifyCredentialStatus = options.verifyCredentialStatus ?? true\n\n const validationResults: W3cVerifyCredentialResult = {\n isValid: false,\n validations: {},\n }\n\n try {\n let credential: W3cJwtVerifiableCredential\n try {\n // If instance is provided as input, we want to validate the credential (otherwise it's done in the fromSerializedJwt method below)\n if (options.credential instanceof W3cJwtVerifiableCredential) {\n MessageValidator.validateSync(options.credential.credential)\n }\n\n credential =\n options.credential instanceof W3cJwtVerifiableCredential\n ? options.credential\n : W3cJwtVerifiableCredential.fromSerializedJwt(options.credential)\n\n // Verify the JWT payload (verifies whether it's not expired, etc...)\n credential.jwt.payload.validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n validationResults.validations.dataModel = {\n isValid: true,\n }\n } catch (error) {\n validationResults.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const issuerVerificationMethod = await this.getVerificationMethodForJwtCredential(agentContext, {\n credential,\n purpose: ['assertionMethod'],\n })\n const issuerPublicKey = getPublicJwkFromVerificationMethod(issuerVerificationMethod)\n\n // Ensure the issuer is trusted according to the (optional) `getTrustedIssuersForVerification`\n // callback. For did-based issuers this is a no-op when no trusted issuers are configured,\n // preserving the previous \"trust any valid signature\" behavior. Throws when the issuer is not trusted.\n await TrustedIssuerContext.ensureTrustedSigner(\n agentContext,\n {\n signer: { method: 'did', didUrl: issuerVerificationMethod.id },\n verification: { type: 'credential', credential },\n },\n options.trustedIssuers\n )\n\n let signatureResult: VerifyJwsResult | undefined\n try {\n // Verify the JWS signature\n signatureResult = await this.jwsService.verifyJws(agentContext, {\n jws: credential.jwt.serializedJwt,\n // We have pre-fetched the key based on the issuer/signer of the credential\n jwsSigner: {\n method: 'did',\n jwk: issuerPublicKey,\n didUrl: issuerVerificationMethod.id,\n },\n })\n\n if (!signatureResult.isValid) {\n validationResults.validations.signature = {\n isValid: false,\n error: new CredoError('Invalid JWS signature'),\n }\n } else {\n validationResults.validations.signature = {\n isValid: true,\n }\n }\n } catch (error) {\n validationResults.validations.signature = {\n isValid: false,\n error,\n }\n }\n\n // Validate whether the credential is signed with the 'issuer' id\n // NOTE: this uses the verificationMethod.controller. We may want to use the verificationMethod.id?\n if (credential.issuerId !== issuerVerificationMethod.controller) {\n validationResults.validations.issuerIsSigner = {\n isValid: false,\n error: new CredoError(\n `Credential is signed using verification method ${issuerVerificationMethod.id}, while the issuer of the credential is '${credential.issuerId}'`\n ),\n }\n } else {\n validationResults.validations.issuerIsSigner = {\n isValid: true,\n }\n }\n\n // Validate whether the `issuer` of the credential is also the signer\n const issuerIsSigner = signatureResult?.jwsSigners.some(\n (jwsSigner) => jwsSigner.jwk.fingerprint === issuerPublicKey.fingerprint\n )\n if (!issuerIsSigner) {\n validationResults.validations.issuerIsSigner = {\n isValid: false,\n error: new CredoError('Credential is not signed by the issuer of the credential'),\n }\n } else {\n validationResults.validations.issuerIsSigner = {\n isValid: true,\n }\n }\n\n // Validate credentialStatus\n if (verifyCredentialStatus && !credential.credentialStatus) {\n validationResults.validations.credentialStatus = {\n isValid: true,\n }\n } else if (verifyCredentialStatus && credential.credentialStatus) {\n validationResults.validations.credentialStatus = {\n isValid: false,\n error: new CredoError('Verifying credential status is not supported for JWT VCs'),\n }\n }\n\n validationResults.isValid = Object.values(validationResults.validations).every((v) => v.isValid)\n\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\n }\n }\n\n /**\n * Signs a presentation including the credentials it includes\n *\n * @param presentation the presentation to be signed\n * @returns the signed presentation\n */\n public async signPresentation(\n agentContext: AgentContext,\n options: W3cJwtSignPresentationOptions\n ): Promise<W3cJwtVerifiablePresentation> {\n // Validate the instance\n MessageValidator.validateSync(options.presentation)\n\n // Get the JWT payload for the JWT based on the JWT Encoding rules form the VC-DATA-MODEL\n // https://www.w3.org/TR/vc-data-model/#jwt-encoding\n const jwtPayload = getJwtPayloadFromPresentation(options.presentation)\n\n // Set the nonce so it's included in the signature\n jwtPayload.additionalClaims.nonce = options.challenge\n jwtPayload.aud = options.domain\n\n const publicJwk = await this.resolveVerificationMethod(agentContext, options.verificationMethod, ['authentication'])\n\n const jwt = await this.jwsService.createJwsCompact(agentContext, {\n payload: jwtPayload,\n keyId: publicJwk.keyId,\n protectedHeaderOptions: {\n typ: 'JWT',\n alg: options.alg,\n kid: options.verificationMethod,\n },\n })\n\n // TODO: this re-parses and validates the presentation in the JWT, which is not necessary.\n // We should somehow create an instance of W3cJwtVerifiablePresentation directly from the JWT\n const jwtVp = W3cJwtVerifiablePresentation.fromSerializedJwt(jwt)\n\n return jwtVp\n }\n\n /**\n * Verifies a presentation including the credentials it includes\n *\n * @param presentation the presentation to be verified\n * @returns the verification result\n */\n public async verifyPresentation(\n agentContext: AgentContext,\n options: W3cJwtVerifyPresentationOptions\n ): Promise<W3cVerifyPresentationResult> {\n const validationResults: W3cVerifyPresentationResult = {\n isValid: false,\n validations: {},\n }\n\n try {\n let presentation: W3cJwtVerifiablePresentation\n try {\n // If instance is provided as input, we want to validate the presentation\n if (options.presentation instanceof W3cJwtVerifiablePresentation) {\n MessageValidator.validateSync(options.presentation.presentation)\n }\n\n presentation =\n options.presentation instanceof W3cJwtVerifiablePresentation\n ? options.presentation\n : W3cJwtVerifiablePresentation.fromSerializedJwt(options.presentation)\n\n // Verify the JWT payload (verifies whether it's not expired, etc...)\n presentation.jwt.payload.validate({\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n\n // Make sure challenge matches nonce\n if (options.challenge !== presentation.jwt.payload.additionalClaims.nonce) {\n throw new CredoError(`JWT payload 'nonce' does not match challenge '${options.challenge}'`)\n }\n\n const audArray = asArray(presentation.jwt.payload.aud)\n if (options.domain && !audArray.includes(options.domain)) {\n throw new CredoError(`JWT payload 'aud' does not include domain '${options.domain}'`)\n }\n\n validationResults.validations.dataModel = {\n isValid: true,\n }\n } catch (error) {\n validationResults.validations.dataModel = {\n isValid: false,\n error,\n }\n\n return validationResults\n }\n\n const proverVerificationMethod = await this.getVerificationMethodForJwtCredential(agentContext, {\n credential: presentation,\n purpose: ['authentication'],\n })\n const proverPublicKey = getPublicJwkFromVerificationMethod(proverVerificationMethod)\n\n let signatureResult: VerifyJwsResult | undefined\n try {\n // Verify the JWS signature\n signatureResult = await this.jwsService.verifyJws(agentContext, {\n jws: presentation.jwt.serializedJwt,\n allowedJwsSignerMethods: ['did'],\n jwsSigner: {\n method: 'did',\n didUrl: proverVerificationMethod.id,\n jwk: proverPublicKey,\n },\n trustedCertificates: [],\n })\n\n if (!signatureResult.isValid) {\n validationResults.validations.presentationSignature = {\n isValid: false,\n error: new CredoError('Invalid JWS signature on presentation'),\n }\n } else {\n validationResults.validations.presentationSignature = {\n isValid: true,\n }\n }\n } catch (error) {\n validationResults.validations.presentationSignature = {\n isValid: false,\n error,\n }\n }\n\n // Validate whether the presentation is signed with the 'holder' id\n // NOTE: this uses the verificationMethod.controller. We may want to use the verificationMethod.id?\n if (presentation.holderId && proverVerificationMethod.controller !== presentation.holderId) {\n validationResults.validations.holderIsSigner = {\n isValid: false,\n error: new CredoError(\n `Presentation is signed using verification method ${proverVerificationMethod.id}, while the holder of the presentation is '${presentation.holderId}'`\n ),\n }\n } else {\n // If no holderId is present, this validation passes by default as there can't be\n // a mismatch between the 'holder' property and the signer of the presentation.\n validationResults.validations.holderIsSigner = {\n isValid: true,\n }\n }\n\n // To keep things simple, we only support JWT VCs in JWT VPs for now\n const credentials = asArray(presentation.presentation.verifiableCredential)\n\n // Verify all credentials in parallel, and await the result\n validationResults.validations.credentials = await Promise.all(\n credentials.map(async (credential) => {\n if (credential instanceof W3cJsonLdVerifiableCredential) {\n return {\n isValid: false,\n error: new CredoError(\n 'Credential is of format ldp_vc. presentations in jwt_vp format can only contain credentials in jwt_vc format'\n ),\n validations: {},\n }\n }\n\n const credentialResult = await this.verifyCredential(agentContext, {\n credential,\n verifyCredentialStatus: options.verifyCredentialStatus,\n trustedIssuers: options.trustedIssuers,\n })\n\n const credentialSubjectAuthentication = validateCredentialSubjectAuthentication(\n credential.credentialSubjectIds,\n proverVerificationMethod.controller\n )\n\n return {\n ...credentialResult,\n isValid: credentialResult.isValid && credentialSubjectAuthentication.isValid,\n validations: {\n ...credentialResult.validations,\n credentialSubjectAuthentication,\n },\n }\n })\n )\n\n // Deeply nested check whether all validations have passed\n validationResults.isValid = Object.values(validationResults.validations).every((v) =>\n Array.isArray(v) ? v.every((vv) => vv.isValid) : v.isValid\n )\n\n return validationResults\n } catch (error) {\n validationResults.error = error\n return validationResults\n }\n }\n\n private async resolveVerificationMethod(\n agentContext: AgentContext,\n verificationMethod: string,\n allowsPurposes?: DidPurpose[]\n ): Promise<PublicJwk> {\n const dids = agentContext.resolve(DidsApi)\n\n const parsedDid = parseDid(verificationMethod)\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\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 *\n * The following methods are used to extract the verification method:\n * - verification method is resolved based on the `kid` in the protected header\n * - either as absolute reference (e.g. `did:example:123#key-1`)\n * - or as relative reference to the `iss` of the JWT (e.g. `iss` is `did:example:123` and `kid` is `#key-1`)\n * - the did document is resolved based on the `iss` field, after which the verification method is extracted based on the `alg`\n * used to sign the JWT and the specified `purpose`. Only a single verification method may be present, and in all other cases,\n * an error is thrown.\n *\n * The signer (`iss`) of the JWT is verified against the `controller` of the verificationMethod resolved in the did\n * document. This means if the `iss` of a credential is `did:example:123` and the controller of the verificationMethod\n * is `did:example:456`, an error is thrown to prevent the JWT from successfully being verified.\n *\n * In addition the JWT must conform to one of the following rules:\n * - MUST be a credential and have an `iss` field and MAY have an absolute or relative `kid`\n * - MUST not be a credential AND ONE of the following:\n * - have an `iss` field and MAY have an absolute or relative `kid`\n * - does not have an `iss` field and MUST have an absolute `kid`\n */\n private async getVerificationMethodForJwtCredential(\n agentContext: AgentContext,\n options: {\n credential: W3cJwtVerifiableCredential | W3cJwtVerifiablePresentation\n purpose?: DidPurpose[]\n }\n ) {\n const { credential, purpose } = options\n const kid = credential.jwt.header.kid\n\n const didResolver = agentContext.dependencyManager.resolve(DidResolverService)\n\n // The signerId is the `holder` of the presentation or the `issuer` of the credential\n // For a credential only the `iss` COULD be enough to resolve the signer key (see method comments)\n const signerId = credential.jwt.payload.iss\n\n let verificationMethod: VerificationMethod\n\n // If the kid starts with # we assume it is a relative did url, and we resolve it based on the `iss` and the `kid`\n if (kid?.startsWith('#')) {\n if (!signerId) {\n throw new CredoError(`JWT 'kid' MUST be absolute when when no 'iss' is present in JWT payload`)\n }\n\n const didDocument = await didResolver.resolveDidDocument(agentContext, signerId)\n verificationMethod = didDocument.dereferenceKey(`${signerId}${kid}`, purpose)\n }\n // this is a full did url (todo check if it contains a #)\n else if (kid && isDid(kid)) {\n const didDocument = await didResolver.resolveDidDocument(agentContext, kid)\n\n verificationMethod = didDocument.dereferenceKey(kid, purpose)\n\n if (signerId && didDocument.id !== signerId) {\n throw new CredoError(`kid '${kid}' does not match id of signer (holder/issuer) '${signerId}'`)\n }\n } else {\n if (!signerId) {\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(\n credential.jwt.header.alg as KnownJwaSignatureAlgorithm\n )\n const supportedVerificationMethodTypes = getSupportedVerificationMethodTypesForPublicJwk(jwkClass)\n\n const didDocument = await didResolver.resolveDidDocument(agentContext, signerId)\n const verificationMethods = didDocument.findVerificationMethodsByTypeAndPurpose(\n supportedVerificationMethodTypes,\n ['assertionMethod']\n )\n\n if (verificationMethods.length === 0) {\n throw new CredoError(\n `No verification methods found for signer '${signerId}' and key type '${jwkClass.name}' for alg '${credential.jwt.header.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 '${signerId}' and key type '${jwkClass.name}' for alg '${credential.jwt.header.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 (signerId && verificationMethod.controller !== signerId) {\n throw new CredoError(\n `Verification method controller '${verificationMethod.controller}' does not match the signer '${signerId}'`\n )\n }\n\n return verificationMethod\n }\n}\n"],"mappings":"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"}