@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 • 36.9 kB
Source Map (JSON)
{"version":3,"file":"SdJwtVcService.mjs","names":[],"sources":["../../../src/modules/sd-jwt-vc/SdJwtVcService.ts"],"sourcesContent":["import type { NonEmptyArray } from '@animo-id/pex'\nimport type { SDJwt } from '@sd-jwt/core'\nimport { decodeSdJwtSync } from '@sd-jwt/decode'\nimport { selectDisclosures } from '@sd-jwt/present'\nimport { SDJwtVcInstance, type VcTFetcher } from '@sd-jwt/sd-jwt-vc'\nimport type { DisclosureFrame, PresentationFrame } from '@sd-jwt/types'\nimport { AgentContext } from '../../agent'\nimport { Hasher, JwtPayload } from '../../crypto'\nimport { CredoError } from '../../error'\nimport { X509Service } from '../../modules/x509/X509Service'\nimport { injectable } from '../../plugins'\nimport type { Query, QueryOptions } from '../../storage/StorageService'\nimport type { JsonObject } from '../../types'\nimport { dateToSeconds, IntegrityVerifier, nowInSeconds, TypedArrayEncoder } from '../../utils'\nimport { getDomainFromUrl } from '../../utils/domain'\nimport { fetchWithTimeout } from '../../utils/fetch'\nimport { getPublicJwkFromVerificationMethod, parseDid } from '../dids'\nimport { KeyManagementApi, PublicJwk } from '../kms'\nimport { ClaimFormat } from '../vc/index'\nimport { type EncodedX509Certificate, X509Certificate, X509ModuleConfig } from '../x509'\nimport { decodeSdJwtVc, sdJwtVcHasher } from './decodeSdJwtVc'\nimport { buildDisclosureFrameForPayload } from './disclosureFrame'\nimport { SdJwtVcRecord, SdJwtVcRepository } from './repository'\nimport { SdJwtVcError } from './SdJwtVcError'\nimport { SdJwtVcModuleConfig } from './SdJwtVcModuleConfig'\nimport type {\n SdJwtVcHeader,\n SdJwtVcHolderBinding,\n SdJwtVcIssuer,\n SdJwtVcPayload,\n SdJwtVcPresentOptions,\n SdJwtVcSignOptions,\n SdJwtVcStoreOptions,\n SdJwtVcVerifyOptions,\n} from './SdJwtVcOptions'\nimport type { SdJwtVcTypeMetadata } from './typeMetadata'\nimport {\n extractKeyFromHolderBinding,\n getSdJwtSigner,\n getSdJwtVerifier,\n parseHolderBindingFromCredential,\n resolveDidUrl,\n resolveSigningPublicJwkFromDidUrl,\n} from './utils'\n\ntype SdJwtVcConfig = SDJwtVcInstance['userConfig']\n\nexport interface SdJwtVc<\n Header extends SdJwtVcHeader = SdJwtVcHeader,\n Payload extends SdJwtVcPayload = SdJwtVcPayload,\n> {\n /**\n * claim format is convenience method added to all credential instances\n */\n claimFormat: ClaimFormat.SdJwtDc\n /**\n * encoded is convenience method added to all credential instances\n */\n encoded: string\n compact: string\n header: Header\n\n /**\n * The holder of the credential\n */\n holder: SdJwtVcHolderBinding | undefined\n\n // TODO: payload type here is a lie, as it is the signed payload (so fields replaced with _sd)\n payload: Payload\n prettyClaims: Payload\n\n kbJwt?: {\n header: Record<string, unknown>\n payload: Record<string, unknown>\n }\n\n /**\n * The key id in the KMS bound to this SD-JWT VC, used for presentations.\n *\n * This will only be set on the holder side if defined on the SdJwtVcRecord\n */\n kmsKeyId?: string\n\n /**\n * The merged/resolved type metadata of the SD-JWT VC.\n */\n typeMetadata?: SdJwtVcTypeMetadata\n}\n\nexport interface VerificationResult {\n isValid: boolean\n isValidJwtPayload?: boolean\n isSignatureValid?: boolean\n isStatusValid?: boolean\n isNotBeforeValid?: boolean\n isExpiryTimeValid?: boolean\n areRequiredClaimsIncluded?: boolean\n isKeyBindingValid?: boolean\n containsExpectedKeyBinding?: boolean\n containsRequiredVcProperties?: boolean\n}\n\n/**\n * @internal\n */\n@injectable()\nexport class SdJwtVcService {\n public constructor(private sdJwtVcRepository: SdJwtVcRepository) {}\n\n public async sign<Payload extends SdJwtVcPayload>(\n agentContext: AgentContext,\n options: SdJwtVcSignOptions<Payload>\n ): Promise<SdJwtVc> {\n const { payload, disclosureFrame, hashingAlgorithm } = options\n\n // default is sha-256\n if (hashingAlgorithm && hashingAlgorithm !== 'sha-256') {\n throw new SdJwtVcError(`Unsupported hashing algorithm used: ${hashingAlgorithm}`)\n }\n\n const issuer = await this.extractKeyFromIssuer(agentContext, options.issuer, true)\n\n // holer binding is optional\n const holderBinding = options.holder ? await extractKeyFromHolderBinding(agentContext, options.holder) : undefined\n\n const header = {\n alg: issuer.alg,\n typ: options.headerType ?? 'dc+sd-jwt',\n kid: issuer.kid,\n x5c: issuer.x5c?.map((cert) => cert.toString('base64')),\n } as const\n\n const sdJwt = new SDJwtVcInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n signer: getSdJwtSigner(agentContext, issuer.publicJwk),\n hashAlg: 'sha-256',\n signAlg: issuer.alg,\n })\n\n if (!payload.vct || typeof payload.vct !== 'string') {\n throw new SdJwtVcError(\"Missing required parameter 'vct'\")\n }\n\n const compact = await sdJwt.issue(\n {\n ...payload,\n cnf: holderBinding?.cnf,\n iss: issuer.iss,\n iat: nowInSeconds(),\n vct: payload.vct,\n },\n disclosureFrame as DisclosureFrame<Payload>,\n { header }\n )\n\n const prettyClaims = (await sdJwt.getClaims(compact)) as Payload\n const decoded = await sdJwt.decode(compact)\n const sdJwtPayload = decoded.jwt?.payload as Payload | undefined\n if (!sdJwtPayload) {\n throw new SdJwtVcError('Invalid sd-jwt-vc state.')\n }\n\n return {\n compact,\n prettyClaims,\n header: header,\n holder: options.holder,\n payload: sdJwtPayload,\n claimFormat: ClaimFormat.SdJwtDc,\n encoded: compact,\n } satisfies SdJwtVc<typeof header, Payload>\n }\n\n public fromCompact<Header extends SdJwtVcHeader = SdJwtVcHeader, Payload extends SdJwtVcPayload = SdJwtVcPayload>(\n compactSdJwtVc: string,\n typeMetadata?: SdJwtVcTypeMetadata\n ): SdJwtVc<Header, Payload> {\n return decodeSdJwtVc(compactSdJwtVc, typeMetadata)\n }\n\n public applyDisclosuresForPayload(compactSdJwtVc: string, requestedPayload: JsonObject): SdJwtVc {\n const decoded = decodeSdJwtSync(compactSdJwtVc, Hasher.hash)\n const presentationFrame = buildDisclosureFrameForPayload(requestedPayload) ?? {}\n\n if (decoded.kbJwt) {\n throw new SdJwtVcError('Cannot apply limit disclosure on an sd-jwt with key binding jwt')\n }\n\n const requiredDisclosures = selectDisclosures(\n decoded.jwt.payload,\n // Map to sd-jwt disclosure format\n decoded.disclosures.map((d) => ({\n digest: d.digestSync({ alg: 'sha-256', hasher: Hasher.hash }),\n encoded: d.encode(),\n key: d.key,\n salt: d.salt,\n value: d.value,\n })),\n presentationFrame as { [key: string]: boolean }\n )\n const [jwt] = compactSdJwtVc.split('~')\n const disclosuresString =\n requiredDisclosures.length > 0 ? `${requiredDisclosures.map((d) => d.encoded).join('~')}~` : ''\n const sdJwt = `${jwt}~${disclosuresString}`\n const disclosedDecoded = decodeSdJwtVc(sdJwt)\n return disclosedDecoded\n }\n\n public async present<Payload extends SdJwtVcPayload = SdJwtVcPayload>(\n agentContext: AgentContext,\n { sdJwtVc, presentationFrame, verifierMetadata, additionalPayload }: SdJwtVcPresentOptions<Payload>\n ): Promise<string> {\n const sdjwt = new SDJwtVcInstance(this.getBaseSdJwtConfig(agentContext))\n const compactSdJwtVc = typeof sdJwtVc === 'string' ? sdJwtVc : sdJwtVc.compact\n const sdJwtVcInstance = await sdjwt.decode(compactSdJwtVc)\n\n const holderBinding = parseHolderBindingFromCredential(sdJwtVcInstance.jwt?.payload)\n if (!holderBinding && verifierMetadata) {\n throw new SdJwtVcError(\"Verifier metadata provided, but credential has no 'cnf' claim to create a KB-JWT from\")\n }\n\n const holder = holderBinding\n ? await extractKeyFromHolderBinding(agentContext, holderBinding, {\n forSigning: true,\n jwkKeyId: typeof sdJwtVc !== 'string' ? sdJwtVc.kmsKeyId : undefined,\n })\n : undefined\n sdjwt.config({\n kbSigner: holder ? getSdJwtSigner(agentContext, holder.publicJwk) : undefined,\n kbSignAlg: holder?.alg,\n })\n\n const compactDerivedSdJwtVc = await sdjwt.present(compactSdJwtVc, presentationFrame as PresentationFrame<Payload>, {\n kb: verifierMetadata\n ? {\n payload: {\n iat: verifierMetadata.issuedAt,\n nonce: verifierMetadata.nonce,\n aud: verifierMetadata.audience,\n ...additionalPayload,\n },\n }\n : undefined,\n })\n\n return compactDerivedSdJwtVc\n }\n\n private assertValidX5cJwtIssuer(\n agentContext: AgentContext,\n iss: string | undefined,\n leafCertificate: X509Certificate\n ) {\n // No 'iss' is allowed for X509\n if (!iss) return\n\n // If iss is present it MUST be an HTTPS url\n if (!iss.startsWith('https://') && !(iss.startsWith('http://') && agentContext.config.allowInsecureHttpUrls)) {\n throw new SdJwtVcError('The X509 certificate issuer must be a HTTPS URI.')\n }\n\n if (!leafCertificate.sanUriNames?.includes(iss) && !leafCertificate.sanDnsNames?.includes(getDomainFromUrl(iss))) {\n throw new SdJwtVcError(\n `The 'iss' claim in the payload does not match a 'SAN-URI' name and the domain extracted from the HTTPS URI does not match a 'SAN-DNS' name in the x5c certificate. Either remove the 'iss' claim or make it match with at least one SAN-URI or DNS-URI entry`\n )\n }\n }\n\n public async verify<Header extends SdJwtVcHeader = SdJwtVcHeader, Payload extends SdJwtVcPayload = SdJwtVcPayload>(\n agentContext: AgentContext,\n { compactSdJwtVc, keyBinding, requiredClaimKeys, fetchTypeMetadata, trustedCertificates, now }: SdJwtVcVerifyOptions\n ): Promise<\n | {\n isValid: true\n sdJwtVc: SdJwtVc<Header, Payload>\n /**\n * The full type metadata chain, can be used for further processing the type metadata.\n *\n * Only populated if `fetchTypeMetadata` is set to true, and the resolver returned a type\n * metadata document.\n */\n typeMetadataChain?: NonEmptyArray<SdJwtVcTypeMetadata>\n }\n | { isValid: false; sdJwtVc?: SdJwtVc<Header, Payload>; error: Error }\n > {\n const sdjwt = new SDJwtVcInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n // We manually fetch later\n loadTypeMetadataFormat: false,\n })\n let sdJwtVc: SDJwt<Header, Payload>\n let holderBinding: SdJwtVcHolderBinding | undefined\n\n try {\n sdJwtVc = (await sdjwt.decode(compactSdJwtVc)) as SDJwt<Header, Payload>\n if (!sdJwtVc.jwt) throw new CredoError('Invalid sd-jwt-vc')\n holderBinding = parseHolderBindingFromCredential(sdJwtVc.jwt.payload) ?? undefined\n } catch (error) {\n return {\n isValid: false,\n error,\n }\n }\n\n const returnSdJwtVc: SdJwtVc<Header, Payload> = {\n payload: sdJwtVc.jwt.payload as Payload,\n header: sdJwtVc.jwt.header as Header,\n compact: compactSdJwtVc,\n prettyClaims: await sdJwtVc.getClaims(sdJwtVcHasher),\n holder: holderBinding,\n\n kbJwt: sdJwtVc.kbJwt\n ? {\n payload: sdJwtVc.kbJwt.payload as Record<string, unknown>,\n header: sdJwtVc.kbJwt.header as Record<string, unknown>,\n }\n : undefined,\n claimFormat: ClaimFormat.SdJwtDc,\n encoded: compactSdJwtVc,\n } satisfies SdJwtVc<Header, Payload>\n\n let typeMetadataChain: NonEmptyArray<SdJwtVcTypeMetadata> | undefined\n try {\n const credentialIssuer = await this.parseIssuerFromCredential(\n agentContext,\n sdJwtVc,\n returnSdJwtVc,\n trustedCertificates\n )\n const issuer = await this.extractKeyFromIssuer(agentContext, credentialIssuer)\n const holder = returnSdJwtVc.holder\n ? await extractKeyFromHolderBinding(agentContext, returnSdJwtVc.holder)\n : undefined\n\n sdjwt.config({\n verifier: getSdJwtVerifier(agentContext, issuer.publicJwk),\n kbVerifier: holder ? getSdJwtVerifier(agentContext, holder.publicJwk) : undefined,\n })\n\n try {\n await sdjwt.verify(compactSdJwtVc, {\n requiredClaimKeys: requiredClaimKeys ? [...requiredClaimKeys, 'vct'] : ['vct'],\n keyBindingNonce: keyBinding?.nonce,\n currentDate: dateToSeconds(now ?? new Date()),\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n } catch (error) {\n return {\n error,\n isValid: false,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n if (sdJwtVc.jwt.header?.typ !== 'vc+sd-jwt' && sdJwtVc.jwt.header?.typ !== 'dc+sd-jwt') {\n return {\n error: new SdJwtVcError(`SD-JWT VC header 'typ' must be 'dc+sd-jwt' or 'vc+sd-jwt'`),\n isValid: false,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n try {\n JwtPayload.fromJson(returnSdJwtVc.payload).validate({\n now: dateToSeconds(now ?? new Date()),\n skewSeconds: agentContext.config.validitySkewSeconds,\n })\n } catch (error) {\n return {\n error,\n isValid: false,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n // If keyBinding is present, verify the key binding\n try {\n if (keyBinding) {\n if (!sdJwtVc.kbJwt || !sdJwtVc.kbJwt.payload) {\n throw new SdJwtVcError('Keybinding is required for verification of the sd-jwt-vc')\n }\n\n // Assert `aud` and `nonce` claims\n if (sdJwtVc.kbJwt.payload.aud !== keyBinding.audience) {\n throw new SdJwtVcError('The key binding JWT does not contain the expected audience')\n }\n\n if (sdJwtVc.kbJwt.payload.nonce !== keyBinding.nonce) {\n throw new SdJwtVcError('The key binding JWT does not contain the expected nonce')\n }\n }\n } catch (error) {\n return {\n error,\n isValid: false,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n if (fetchTypeMetadata) {\n // We allow vct without type metadata for now (and don't fail if the retrieval fails)\n // Integrity check must pass though.\n const resolvedTypeMetadata = await this.fetchTypeMetadata(agentContext, returnSdJwtVc, {\n throwErrorOnFetchError: false,\n throwErrorOnUnsupportedVctValue: false,\n })\n\n returnSdJwtVc.typeMetadata = resolvedTypeMetadata?.mergedTypeMetadata\n typeMetadataChain = resolvedTypeMetadata?.typeMetadataChain\n }\n } catch (error) {\n return {\n isValid: false,\n error,\n sdJwtVc: returnSdJwtVc,\n }\n }\n\n return {\n isValid: true,\n sdJwtVc: returnSdJwtVc,\n typeMetadataChain,\n }\n }\n\n /**\n * Resolve the type metadata for an SD-JWT instance.\n *\n * This method resolves the `vct` value, and any `extends` values.\n */\n public async fetchTypeMetadata(\n agentContext: AgentContext,\n sdJwtVc: SdJwtVc,\n {\n throwErrorOnFetchError = true,\n throwErrorOnUnsupportedVctValue = true,\n }: { throwErrorOnFetchError?: boolean; throwErrorOnUnsupportedVctValue?: boolean } = {}\n ) {\n const sdjwt = new SDJwtVcInstance({\n ...this.getBaseSdJwtConfig(agentContext),\n vctFetcher: this.getVctFetcher(agentContext, {\n baseVct: sdJwtVc.payload.vct,\n throwErrorOnFetchError,\n throwErrorOnUnsupportedVctValue,\n }),\n })\n\n const typeMetadata = await sdjwt.getVct(sdJwtVc.compact)\n return typeMetadata\n }\n\n public async store(agentContext: AgentContext, options: SdJwtVcStoreOptions) {\n await this.sdJwtVcRepository.save(agentContext, options.record)\n return options.record\n }\n\n public async getById(agentContext: AgentContext, id: string): Promise<SdJwtVcRecord> {\n return await this.sdJwtVcRepository.getById(agentContext, id)\n }\n\n public async getAll(agentContext: AgentContext): Promise<Array<SdJwtVcRecord>> {\n return await this.sdJwtVcRepository.getAll(agentContext)\n }\n\n public async findByQuery(\n agentContext: AgentContext,\n query: Query<SdJwtVcRecord>,\n queryOptions?: QueryOptions\n ): Promise<Array<SdJwtVcRecord>> {\n return await this.sdJwtVcRepository.findByQuery(agentContext, query, queryOptions)\n }\n\n public async deleteById(agentContext: AgentContext, id: string) {\n await this.sdJwtVcRepository.deleteById(agentContext, id)\n }\n\n public async update(agentContext: AgentContext, sdJwtVcRecord: SdJwtVcRecord) {\n await this.sdJwtVcRepository.update(agentContext, sdJwtVcRecord)\n }\n\n private async extractKeyFromIssuer(agentContext: AgentContext, issuer: SdJwtVcIssuer, forSigning = false) {\n if (issuer.method === 'did') {\n const parsedDid = parseDid(issuer.didUrl)\n if (!parsedDid.fragment) {\n throw new SdJwtVcError(\n `didUrl '${issuer.didUrl}' does not contain a '#'. Unable to derive key from did document`\n )\n }\n\n let publicJwk: PublicJwk\n if (forSigning) {\n publicJwk = await resolveSigningPublicJwkFromDidUrl(agentContext, issuer.didUrl)\n } else {\n const { verificationMethod } = await resolveDidUrl(agentContext, issuer.didUrl)\n publicJwk = getPublicJwkFromVerificationMethod(verificationMethod)\n }\n\n const supportedSignatureAlgorithms = publicJwk.supportedSignatureAlgorithms\n if (supportedSignatureAlgorithms.length === 0) {\n throw new SdJwtVcError(\n `No supported JWA signature algorithms found for key ${publicJwk.jwkTypeHumanDescription}`\n )\n }\n const alg = supportedSignatureAlgorithms[0]\n\n return {\n alg,\n publicJwk,\n iss: parsedDid.did,\n kid: `#${parsedDid.fragment}`,\n }\n }\n\n if (issuer.method === 'x5c') {\n const leafCertificate = issuer.x5c[0]\n if (!leafCertificate) {\n throw new SdJwtVcError(\"Empty 'x5c' array provided\")\n }\n\n if (forSigning && !leafCertificate.publicJwk.hasKeyId) {\n throw new SdJwtVcError(\"Expected leaf certificate in 'x5c' array to have a key id configured.\")\n }\n\n const publicJwk = leafCertificate.publicJwk\n const supportedSignatureAlgorithms = publicJwk.supportedSignatureAlgorithms\n if (supportedSignatureAlgorithms.length === 0) {\n throw new SdJwtVcError(\n `No supported JWA signature algorithms found for key ${publicJwk.jwkTypeHumanDescription}`\n )\n }\n const alg = supportedSignatureAlgorithms[0]\n\n this.assertValidX5cJwtIssuer(agentContext, issuer.issuer, leafCertificate)\n\n return {\n publicJwk,\n iss: issuer.issuer,\n x5c: issuer.x5c,\n alg,\n }\n }\n\n throw new SdJwtVcError(\"Unsupported credential issuer. Only 'did' and 'x5c' is supported at the moment.\")\n }\n\n private async parseIssuerFromCredential<Header extends SdJwtVcHeader, Payload extends SdJwtVcPayload>(\n agentContext: AgentContext,\n sdJwtVc: SDJwt<Header, Payload>,\n credoSdJwtVc: SdJwtVc<Header, Payload>,\n _trustedCertificates?: EncodedX509Certificate[]\n ): Promise<SdJwtVcIssuer> {\n const x509Config = agentContext.dependencyManager.resolve(X509ModuleConfig)\n if (!sdJwtVc.jwt?.payload) {\n throw new SdJwtVcError('Credential not exist')\n }\n\n const iss = sdJwtVc.jwt.payload.iss as string | undefined\n\n if (sdJwtVc.jwt.header?.x5c) {\n if (!Array.isArray(sdJwtVc.jwt.header.x5c)) {\n throw new SdJwtVcError('Invalid x5c header in credential. Not an array.')\n }\n if (sdJwtVc.jwt.header.x5c.length === 0) {\n throw new SdJwtVcError('Invalid x5c header in credential. Empty array.')\n }\n if (sdJwtVc.jwt.header.x5c.some((x5c) => typeof x5c !== 'string')) {\n throw new SdJwtVcError('Invalid x5c header in credential. Not an array of strings.')\n }\n\n let trustedCertificates = _trustedCertificates\n const certificateChain = sdJwtVc.jwt.header.x5c.map((cert) => X509Certificate.fromEncodedCertificate(cert))\n\n if (!trustedCertificates) {\n trustedCertificates =\n (await x509Config.getTrustedCertificatesForVerification?.(agentContext, {\n certificateChain,\n verification: {\n type: 'credential',\n credential: credoSdJwtVc,\n },\n })) ?? x509Config.trustedCertificates\n }\n\n if (!trustedCertificates) {\n throw new SdJwtVcError(\n 'No trusted certificates configured for X509 certificate chain validation. Issuer cannot be verified.'\n )\n }\n\n await X509Service.validateCertificateChain(agentContext, {\n certificateChain: sdJwtVc.jwt.header.x5c,\n trustedCertificates,\n })\n\n return {\n method: 'x5c',\n x5c: certificateChain,\n issuer: iss,\n }\n }\n\n if (iss?.startsWith('did:')) {\n // If `did` is used, we require a relative KID to be present to identify\n // the key used by issuer to sign the sd-jwt-vc\n\n if (!sdJwtVc.jwt?.header) {\n throw new SdJwtVcError('Credential does not contain a header')\n }\n\n if (!sdJwtVc.jwt.header.kid) {\n throw new SdJwtVcError('Credential does not contain a kid in the header')\n }\n\n const issuerKid = sdJwtVc.jwt.header.kid as string\n\n let didUrl: string\n if (issuerKid.startsWith('#')) {\n didUrl = `${iss}${issuerKid}`\n } else if (issuerKid.startsWith('did:')) {\n const didFromKid = parseDid(issuerKid)\n if (didFromKid.did !== iss) {\n throw new SdJwtVcError(\n `kid in header is an absolute DID URL, but the did (${didFromKid.did}) does not match with the 'iss' did (${iss})`\n )\n }\n\n didUrl = issuerKid\n } else {\n throw new SdJwtVcError(\n 'Invalid issuer kid for did. Only absolute or relative (starting with #) did urls are supported.'\n )\n }\n\n return {\n method: 'did',\n didUrl,\n }\n }\n\n throw new SdJwtVcError('Unsupported signing method for SD-JWT VC. Only did and x5c are supported at the moment.')\n }\n\n private getBaseSdJwtConfig(agentContext: AgentContext): SdJwtVcConfig {\n const kms = agentContext.resolve(KeyManagementApi)\n\n return {\n hasher: sdJwtVcHasher,\n statusListFetcher: this.getStatusListFetcher(agentContext),\n saltGenerator: (length) => TypedArrayEncoder.toBase64Url(kms.randomBytes({ length })).slice(0, length),\n }\n }\n\n private getStatusListFetcher(agentContext: AgentContext) {\n return async (uri: string) => {\n const response = await fetchWithTimeout(agentContext.config.agentDependencies.fetch, uri, {\n headers: {\n Accept: 'application/statuslist+jwt',\n },\n })\n\n if (!response.ok) {\n throw new CredoError(\n `Received invalid response with status ${\n response.status\n } when fetching status list from ${uri}. ${await response.text()}`\n )\n }\n\n return await response.text()\n }\n }\n\n private getVctFetcher(\n agentContext: AgentContext,\n {\n baseVct,\n throwErrorOnFetchError = true,\n throwErrorOnUnsupportedVctValue = true,\n }: { baseVct: string; throwErrorOnFetchError?: boolean; throwErrorOnUnsupportedVctValue?: boolean }\n ): VcTFetcher {\n const sdJwtVcConfig = agentContext.dependencyManager.resolve(SdJwtVcModuleConfig)\n return async (uri: string, integrity) => {\n if (sdJwtVcConfig.customTypeMetadataResolver) {\n const customTypeMetadata = await sdJwtVcConfig.customTypeMetadataResolver(uri, integrity, {\n isExtendedVct: uri !== baseVct,\n defaultResolver: (userOverrideOptions) =>\n this.httpsTypeMetadataResolver(agentContext, uri, integrity, {\n throwErrorOnFetchError: userOverrideOptions.throwErrorOnFetchError ?? throwErrorOnFetchError,\n throwErrorOnUnsupportedVctValue:\n userOverrideOptions.throwErrorOnUnsupportedVctValue ?? throwErrorOnUnsupportedVctValue,\n isExtendedVct: uri !== baseVct,\n }),\n })\n\n return customTypeMetadata as SdJwtVcTypeMetadata | undefined\n }\n\n if (!uri.startsWith('https://')) {\n if (!throwErrorOnUnsupportedVctValue) return undefined\n throw new SdJwtVcError(\n `Unable to resolve type metadata for vct '${uri}'. Only https supported and no 'customTypeMetadataResolver' provided in agent config.`\n )\n }\n\n const defaultTypeMetadata = await this.httpsTypeMetadataResolver(agentContext, uri, integrity, {\n throwErrorOnFetchError,\n throwErrorOnUnsupportedVctValue,\n isExtendedVct: uri !== baseVct,\n })\n return defaultTypeMetadata as SdJwtVcTypeMetadata | undefined\n }\n }\n\n private async httpsTypeMetadataResolver(\n agentContext: AgentContext,\n vct: string,\n integrity: string | undefined,\n {\n throwErrorOnFetchError,\n throwErrorOnUnsupportedVctValue,\n isExtendedVct,\n }: { throwErrorOnFetchError: boolean; throwErrorOnUnsupportedVctValue: boolean; isExtendedVct?: boolean }\n ) {\n if (!vct.startsWith('https://')) {\n if (!throwErrorOnUnsupportedVctValue) return undefined\n throw new SdJwtVcError(\n `Unable to resolve type metadata for vct '${vct}'. Only https supported for default resolver`\n )\n }\n let firstError: Error | undefined\n\n // Fist try the new type metadata URL\n // We add a catch, so that if e.g. the request fails due to CORS (which throws an error\n // we will still continue trying the legacy url)\n const firstResponse = await fetchWithTimeout(agentContext.config.agentDependencies.fetch, vct).catch((error) => {\n firstError = error\n return undefined\n })\n let response = firstResponse\n\n // If the response is not ok, try the legacy URL (will be removed in 0.7)\n if (!response || !response?.ok) {\n // modify the uri based on https://www.ietf.org/archive/id/draft-ietf-oauth-sd-jwt-vc-04.html#section-6.3.1\n const vctElements = vct.split('/')\n vctElements.splice(3, 0, '.well-known/vct')\n const legacyVctUrl = vctElements.join('/')\n\n response = await fetchWithTimeout(agentContext.config.agentDependencies.fetch, legacyVctUrl).catch(\n () => undefined\n )\n }\n\n if (!response?.ok) {\n if (!throwErrorOnFetchError) return undefined\n\n if (firstResponse) {\n throw new SdJwtVcError(\n `Unable to resolve type metadata vct '${vct}'. Fetch returned a non-successful ${firstResponse.status} response. ${await firstResponse.text()}.`,\n { cause: firstError }\n )\n } else {\n throw new SdJwtVcError(\n `Unable to resolve type metadata vct '${vct}'. Fetch returned a non-successful response.`,\n { cause: firstError }\n )\n }\n }\n\n const typeMetadata = (await response.clone().json()) as Record<string, unknown>\n if (integrity) {\n if (typeof integrity !== 'string') {\n throw new SdJwtVcError(\n `Found '${isExtendedVct ? 'extends' : 'vct'}#integrity' with value '${integrity}' but value was not of type 'string'.`\n )\n }\n\n IntegrityVerifier.verifyIntegrity(new Uint8Array(await response.arrayBuffer()), integrity)\n }\n\n return typeMetadata\n }\n}\n"],"mappings":"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"}