{"version":3,"file":"callbacks.mjs","names":[],"sources":["../../src/shared/callbacks.ts"],"sourcesContent":["import {\n  AgentContext,\n  CredoError,\n  Hasher,\n  JsonEncoder,\n  JwsService,\n  type JwsSignerWithJwk,\n  JwtPayload,\n  Kms,\n  TypedArrayEncoder,\n  X509Certificate,\n  X509ModuleConfig,\n  X509Service,\n} from '@credo-ts/core'\nimport type {\n  CallbackContext,\n  ClientAuthenticationCallback,\n  DecryptJweCallback,\n  EncryptJweCallback,\n  Jwk,\n  SignJwtCallback,\n  VerifyJwtCallback,\n} from '@openid4vc/oauth2'\nimport { clientAuthenticationDynamic, decodeJwtHeader } from '@openid4vc/oauth2'\nimport type { OpenId4VcIssuerRecord } from '../openid4vc-issuer/repository'\n\nimport { getPublicJwkFromDid } from './utils'\n\nexport function getOid4vcJwtVerifyCallback(\n  agentContext: AgentContext,\n  options?: {\n    trustedCertificates?: string[]\n\n    issuanceSessionId?: string\n\n    /**\n     * Whether this verification callback should assume a JAR authorization is verified\n     * Starting from OID4VP draft 24 the JAR must use oauth-authz-req+jwt header typ\n     * but for backwards compatiblity we need to also handle the case where the header typ is different\n     * @default false\n     */\n    isAuthorizationRequestJwt?: boolean\n  }\n): VerifyJwtCallback {\n  const jwsService = agentContext.dependencyManager.resolve(JwsService)\n\n  return async (signer, { compact, header, payload }) => {\n    let trustedCertificates = options?.trustedCertificates\n    if (\n      signer.method === 'x5c' &&\n      (header.typ === 'oauth-authz-req+jwt' || options?.isAuthorizationRequestJwt) &&\n      !trustedCertificates\n    ) {\n      const x509Config = agentContext.dependencyManager.resolve(X509ModuleConfig)\n      const certificateChain = signer.x5c?.map((cert) => X509Certificate.fromEncodedCertificate(cert))\n\n      trustedCertificates = await x509Config.getTrustedCertificatesForVerification?.(agentContext, {\n        certificateChain,\n        verification: {\n          type: 'oauth2SecuredAuthorizationRequest',\n          authorizationRequest: {\n            jwt: compact,\n            payload: JwtPayload.fromJson(payload),\n          },\n        },\n      })\n    }\n\n    if (\n      signer.method === 'x5c' &&\n      (header.typ === 'keyattestation+jwt' || header.typ === 'key-attestation+jwt') &&\n      options?.issuanceSessionId &&\n      !trustedCertificates\n    ) {\n      const x509Config = agentContext.dependencyManager.resolve(X509ModuleConfig)\n      const certificateChain = signer.x5c?.map((cert) => X509Certificate.fromEncodedCertificate(cert))\n\n      trustedCertificates = await x509Config.getTrustedCertificatesForVerification?.(agentContext, {\n        certificateChain,\n        verification: {\n          type: 'openId4VciKeyAttestation',\n          openId4VcIssuanceSessionId: options.issuanceSessionId,\n          keyAttestation: {\n            jwt: compact,\n            payload: JwtPayload.fromJson(payload),\n          },\n        },\n      })\n    }\n\n    if (signer.method === 'x5c' && header.typ === 'openidvci-issuer-metadata+jwt' && !trustedCertificates) {\n      const x509Config = agentContext.dependencyManager.resolve(X509ModuleConfig)\n      const certificateChain = signer.x5c?.map((cert) => X509Certificate.fromEncodedCertificate(cert))\n\n      trustedCertificates = await x509Config.getTrustedCertificatesForVerification?.(agentContext, {\n        certificateChain,\n        verification: {\n          type: 'openId4VciCredentialIssuerMetadata',\n          credentialIssuerMetadata: {\n            jwt: compact,\n            payload: JwtPayload.fromJson(payload),\n          },\n        },\n      })\n    }\n\n    if (\n      signer.method === 'x5c' &&\n      header.typ === 'oauth-client-attestation+jwt' &&\n      options?.issuanceSessionId &&\n      !trustedCertificates\n    ) {\n      const x509Config = agentContext.dependencyManager.resolve(X509ModuleConfig)\n      const certificateChain = signer.x5c?.map((cert) => X509Certificate.fromEncodedCertificate(cert))\n\n      trustedCertificates = await x509Config.getTrustedCertificatesForVerification?.(agentContext, {\n        certificateChain,\n        verification: {\n          type: 'oauth2ClientAttestation',\n          openId4VcIssuanceSessionId: options.issuanceSessionId,\n          clientAttestation: {\n            jwt: compact,\n            payload: JwtPayload.fromJson(payload),\n          },\n        },\n      })\n    }\n\n    const alg = signer.alg as Kms.KnownJwaSignatureAlgorithm\n    if (!Object.values(Kms.KnownJwaSignatureAlgorithms).includes(alg)) {\n      throw new CredoError(`Unsupported jwa signatre algorithm '${alg}'`)\n    }\n\n    const jwsSigner: JwsSignerWithJwk | undefined =\n      signer.method === 'did'\n        ? {\n            method: 'did',\n            didUrl: signer.didUrl,\n            jwk: await getPublicJwkFromDid(agentContext, signer.didUrl),\n          }\n        : signer.method === 'jwk'\n          ? {\n              method: 'jwk',\n              jwk: Kms.PublicJwk.fromUnknown(signer.publicJwk),\n            }\n          : signer.method === 'x5c'\n            ? {\n                method: 'x5c',\n                x5c: signer.x5c,\n                jwk: X509Certificate.fromEncodedCertificate(signer.x5c[0]).publicJwk,\n              }\n            : undefined\n\n    if (!jwsSigner) {\n      throw new CredoError(`Unable to verify jws with unsupported jws signer method '${signer.method}'`)\n    }\n\n    const { isValid, jwsSigners } = await jwsService.verifyJws(agentContext, {\n      jws: compact,\n      trustedCertificates,\n      jwsSigner,\n    })\n\n    if (!isValid) {\n      return { verified: false, signerJwk: undefined }\n    }\n\n    const signerJwk = jwsSigners[0].jwk.toJson() as Jwk\n    return { verified: true, signerJwk }\n  }\n}\n\nexport function getOid4vcEncryptJweCallback(agentContext: AgentContext): EncryptJweCallback {\n  const kms = agentContext.dependencyManager.resolve(Kms.KeyManagementApi)\n\n  return async (jweEncryptor, compact) => {\n    if (jweEncryptor.method !== 'jwk') {\n      throw new CredoError(\n        `Jwt encryption method '${jweEncryptor.method}' is not supported for jwt signer. Only 'jwk' is supported.`\n      )\n    }\n\n    // TODO: we should probably add a key id or ference to the jweEncryptor/jwsSigner in\n    // oid4vc-ts so we can keep a reference to the key\n    const jwk = Kms.PublicJwk.fromUnknown(jweEncryptor.publicJwk)\n    if (!jwk.hasKeyId) {\n      throw new CredoError('Expected kid to be defined on the JWK')\n    }\n\n    if (jweEncryptor.alg !== 'ECDH-ES') {\n      throw new CredoError(\"Only 'ECDH-ES' is supported as 'alg' value for JARM response encryption\")\n    }\n\n    if (jweEncryptor.enc !== 'A256GCM' && jweEncryptor.enc !== 'A128GCM' && jweEncryptor.enc !== 'A128CBC-HS256') {\n      throw new CredoError(\n        \"Only 'A256GCM', 'A128GCM', and 'A128CBC-HS256' is supported as 'enc' value for JARM response encryption\"\n      )\n    }\n\n    const jwkJson = jwk.toJson()\n    if (jwkJson.kty !== 'EC' && jwkJson.kty !== 'OKP') {\n      throw new CredoError(`Expected EC or OKP jwk for encryption, found ${Kms.getJwkHumanDescription(jwkJson)}`)\n    }\n\n    if (jwkJson.crv === 'Ed25519') {\n      throw new CredoError(`Expected ${jwkJson.kty} with crv X25519, found ${Kms.getJwkHumanDescription(jwkJson)}`)\n    }\n\n    // TODO: create a JWE service that handles this\n    const ephmeralKey = await kms.createKey({\n      type: jwkJson,\n    })\n\n    try {\n      const header = {\n        kid: jweEncryptor.publicJwk.kid,\n        apu: jweEncryptor.apu,\n        apv: jweEncryptor.apv,\n        enc: jweEncryptor.enc,\n        alg: 'ECDH-ES',\n        epk: ephmeralKey.publicJwk,\n      }\n      const encodedHeader = JsonEncoder.toBase64Url(header)\n\n      const encrypted = await kms.encrypt({\n        key: {\n          keyAgreement: {\n            // FIXME: We can make the keyId optional for ECDH-ES\n            // That way we don't have to store the key\n            keyId: ephmeralKey.keyId,\n            algorithm: 'ECDH-ES',\n            apu: jweEncryptor.apu ? TypedArrayEncoder.fromBase64Url(jweEncryptor.apu) : undefined,\n            apv: jweEncryptor.apv ? TypedArrayEncoder.fromBase64Url(jweEncryptor.apv) : undefined,\n            externalPublicJwk: jwkJson,\n          },\n        },\n        data: TypedArrayEncoder.fromUtf8String(compact),\n        encryption: {\n          algorithm: jweEncryptor.enc,\n          aad: TypedArrayEncoder.fromUtf8String(encodedHeader),\n        },\n      })\n\n      if (!encrypted.iv || !encrypted.tag) {\n        throw new CredoError(\"Expected 'iv' and 'tag' to be defined\")\n      }\n\n      const compactJwe = `${encodedHeader}..${TypedArrayEncoder.toBase64Url(encrypted.iv)}.${TypedArrayEncoder.toBase64Url(\n        encrypted.encrypted\n      )}.${TypedArrayEncoder.toBase64Url(encrypted.tag)}`\n\n      return { encryptionJwk: jweEncryptor.publicJwk, jwe: compactJwe }\n    } finally {\n      // Delete the key\n      await kms.deleteKey({\n        keyId: ephmeralKey.keyId,\n      })\n    }\n  }\n}\n\nexport function getOid4vcDecryptJweCallback(agentContext: AgentContext): DecryptJweCallback {\n  const kms = agentContext.resolve(Kms.KeyManagementApi)\n  return async (jwe, options) => {\n    // TODO: use custom header zod schema to limit which algorithms can be used\n    const { header } = decodeJwtHeader({ jwt: jwe })\n\n    let kid = options?.jwk?.kid ?? header.kid\n    if (!kid) {\n      throw new CredoError('Uanbel to decrypt jwe. No kid or jwk found')\n    }\n\n    // Previously we used the fingerprint as the kid for JARM\n    // We try to parse it as fingerprint if it starts with z (base58 encoding)\n    // It's not 100%\n    if (kid.startsWith('z')) {\n      try {\n        const publicJwk = Kms.PublicJwk.fromFingerprint(kid)\n        if (publicJwk) kid = publicJwk.legacyKeyId\n      } catch {\n        // no-op\n      }\n    }\n\n    // TODO: decodeJwe method in oid4vc-ts\n    // encryption key is not used (we don't use key wrapping)\n    const [encodedHeader /* encryptionKey */, , encodedIv, encodedCiphertext, encodedTag] = jwe.split('.')\n\n    if (header.alg !== 'ECDH-ES') {\n      throw new CredoError(\"Only 'ECDH-ES' is supported as 'alg' value for JARM response decryption\")\n    }\n\n    if (header.enc !== 'A256GCM' && header.enc !== 'A128GCM' && header.enc !== 'A128CBC-HS256') {\n      throw new CredoError(\n        \"Only 'A256GCM', 'A128GCM', and 'A128CBC-HS256' is supported as 'enc' value for JARM response decryption\"\n      )\n    }\n\n    let decryptedPayload: string\n    let publicJwk: Kms.PublicJwk\n\n    const epk = Kms.PublicJwk.fromUnknown(header.epk)\n\n    try {\n      const decrypted = await kms.decrypt({\n        encrypted: TypedArrayEncoder.fromBase64Url(encodedCiphertext),\n        decryption: {\n          algorithm: header.enc,\n          // aad is the base64 encoded bytes (not just the bytes)\n          aad: TypedArrayEncoder.fromUtf8String(encodedHeader),\n          iv: TypedArrayEncoder.fromBase64Url(encodedIv),\n          tag: TypedArrayEncoder.fromBase64Url(encodedTag),\n        },\n        key: {\n          keyAgreement: {\n            algorithm: header.alg,\n            externalPublicJwk: epk.toJson() as Kms.KmsJwkPublicEcdh,\n            keyId: kid,\n            apu: typeof header.apu === 'string' ? TypedArrayEncoder.fromBase64Url(header.apu) : undefined,\n            apv: typeof header.apv === 'string' ? TypedArrayEncoder.fromBase64Url(header.apv) : undefined,\n          },\n        },\n      })\n\n      // TODO: decrypt should return the public jwk instance\n      publicJwk = Kms.PublicJwk.fromUnknown(\n        await kms.getPublicKey({\n          keyId: kid,\n        })\n      )\n\n      decryptedPayload = TypedArrayEncoder.toUtf8String(decrypted.data)\n    } catch (error) {\n      agentContext.config.logger.error('Error decrypting JWE', {\n        error,\n      })\n      return {\n        decrypted: false,\n        encryptionJwk: options?.jwk,\n        payload: undefined,\n        header,\n      }\n    }\n\n    return {\n      decrypted: true,\n      decryptionJwk: publicJwk.toJson() as Jwk,\n      payload: decryptedPayload,\n      header,\n    }\n  }\n}\n\nexport function getOid4vcJwtSignCallback(agentContext: AgentContext): SignJwtCallback {\n  const jwsService = agentContext.dependencyManager.resolve(JwsService)\n\n  return async (signer, { payload, header }) => {\n    if (signer.method === 'custom' || signer.method === 'federation') {\n      throw new CredoError(`Jwt signer method 'custom' and 'federation' are not supported for jwt signer.`)\n    }\n\n    if (signer.method === 'x5c') {\n      const leafCertificate = X509Service.getLeafCertificate(agentContext, { certificateChain: signer.x5c })\n\n      const jws = await jwsService.createJwsCompact(agentContext, {\n        protectedHeaderOptions: { ...header, alg: signer.alg as Kms.KnownJwaSignatureAlgorithm, jwk: undefined },\n        payload: JwtPayload.fromJson(payload),\n        keyId: signer.kid ?? leafCertificate.publicJwk.keyId,\n      })\n\n      return { jwt: jws, signerJwk: leafCertificate.publicJwk.toJson() as Jwk }\n    }\n\n    // TOOD: createJwsCompact should return the Jwk, so we don't have to reoslve it here\n    const publicJwk =\n      signer.method === 'did'\n        ? await getPublicJwkFromDid(agentContext, signer.didUrl)\n        : Kms.PublicJwk.fromUnknown(signer.publicJwk)\n\n    if (!publicJwk.supportedSignatureAlgorithms.includes(signer.alg as Kms.KnownJwaSignatureAlgorithm)) {\n      throw new CredoError(\n        `jwk ${publicJwk.jwkTypeHumanDescription} does not support JWS signature alg '${signer.alg}'`\n      )\n    }\n\n    const jwt = await jwsService.createJwsCompact(agentContext, {\n      protectedHeaderOptions: {\n        ...header,\n        jwk: header.jwk ? publicJwk : undefined,\n        alg: signer.alg as Kms.KnownJwaSignatureAlgorithm,\n      },\n      payload: JsonEncoder.toUint8Array(payload),\n      keyId: signer.kid ?? publicJwk.keyId,\n    })\n\n    return { jwt, signerJwk: publicJwk.toJson() as Jwk }\n  }\n}\n\nexport function getOid4vcCallbacks(\n  agentContext: AgentContext,\n  options?: {\n    trustedCertificates?: string[]\n    isVerifyOpenId4VpAuthorizationRequest?: boolean\n    issuanceSessionId?: string\n  }\n) {\n  const kms = agentContext.resolve(Kms.KeyManagementApi)\n\n  return {\n    hash: (data, alg) => Hasher.hash(data, alg.toLowerCase()),\n    generateRandom: (length) => kms.randomBytes({ length }),\n    signJwt: getOid4vcJwtSignCallback(agentContext),\n    clientAuthentication: () => {\n      throw new CredoError('Did not expect client authentication to be called.')\n    },\n    verifyJwt: getOid4vcJwtVerifyCallback(agentContext, {\n      trustedCertificates: options?.trustedCertificates,\n      isAuthorizationRequestJwt: options?.isVerifyOpenId4VpAuthorizationRequest,\n      issuanceSessionId: options?.issuanceSessionId,\n    }),\n    fetch: agentContext.config.agentDependencies.fetch,\n    encryptJwe: getOid4vcEncryptJweCallback(agentContext),\n    decryptJwe: getOid4vcDecryptJweCallback(agentContext),\n    getX509CertificateMetadata: (certificate: string) => {\n      const leafCertificate = X509Service.getLeafCertificate(agentContext, { certificateChain: [certificate] })\n      return {\n        sanDnsNames: leafCertificate.sanDnsNames,\n        sanUriNames: leafCertificate.sanUriNames,\n      }\n    },\n  } satisfies Partial<CallbackContext>\n}\n\n/**\n * Allows us to authenticate when making requests to an external\n * authorization server\n */\nexport function dynamicOid4vciClientAuthentication(\n  agentContext: AgentContext,\n  issuerRecord: OpenId4VcIssuerRecord\n): ClientAuthenticationCallback {\n  return (callbackOptions) => {\n    const authorizationServer = issuerRecord.authorizationServerConfigs?.find(\n      (a) => a.issuer === callbackOptions.authorizationServerMetadata.issuer\n    )\n\n    if (!authorizationServer) {\n      // No client authentication if authorization server is not configured\n      agentContext.config.logger.debug(\n        `Unknown authorization server '${callbackOptions.authorizationServerMetadata.issuer}' for issuer '${issuerRecord.issuerId}' for request to '${callbackOptions.url}'`\n      )\n      return\n    }\n\n    if (!authorizationServer.clientAuthentication) {\n      throw new CredoError(\n        `Unable to authenticate to authorization server '${authorizationServer.issuer}' for issuer '${issuerRecord.issuerId}' for request to '${callbackOptions.url}'. Make sure to configure a 'clientId' and 'clientSecret' for the authorization server on the issuer record.`\n      )\n    }\n\n    return clientAuthenticationDynamic({\n      clientId: authorizationServer.clientAuthentication.clientId,\n      clientSecret: authorizationServer.clientAuthentication.clientSecret,\n    })(callbackOptions)\n  }\n}\n"],"mappings":"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"}