{"version":3,"file":"OpenId4VciHolderService.mjs","names":[],"sources":["../../src/openid4vc-holder/OpenId4VciHolderService.ts"],"sourcesContent":["import {\n  AgentContext,\n  CredoError,\n  DidsApi,\n  InjectionSymbols,\n  inject,\n  injectable,\n  Kms,\n  type Logger,\n  Mdoc,\n  MdocApi,\n  MdocRecord,\n  type MdocRecordInstances,\n  parseDid,\n  replaceError,\n  SdJwtVcApi,\n  SdJwtVcRecord,\n  type SdJwtVcRecordInstances,\n  SignatureSuiteRegistry,\n  TypedArrayEncoder,\n  W3cCredentialRecord,\n  type W3cCredentialRecordInstances,\n  W3cCredentialService,\n  W3cJsonLdCredentialService,\n  W3cJsonLdVerifiableCredential,\n  W3cJwtVerifiableCredential,\n  W3cV2CredentialRecord,\n  type W3cV2CredentialRecordInstances,\n  W3cV2CredentialService,\n  W3cV2SdJwtVerifiableCredential,\n} from '@credo-ts/core'\nimport {\n  type AccessTokenResponse,\n  type AuthorizationErrorResponse,\n  authorizationCodeGrantIdentifier,\n  type CallbackContext,\n  clientAuthenticationAnonymous,\n  clientAuthenticationClientAttestationJwt,\n  clientAuthenticationNone,\n  getAuthorizationServerMetadataFromList,\n  type Jwk,\n  Oauth2Client,\n  Oauth2ServerErrorResponseError,\n  preAuthorizedCodeGrantIdentifier,\n  type RequestDpopOptions,\n  refreshTokenGrantIdentifier,\n} from '@openid4vc/oauth2'\nimport {\n  AuthorizationFlow,\n  type CredentialResponse,\n  type DeferredCredentialResponse,\n  determineAuthorizationServerForCredentialOffer,\n  type IssuerMetadataResult,\n  Openid4vciClient,\n  Openid4vciRetrieveCredentialsError,\n  Openid4vciVersion,\n  parseKeyAttestationJwt,\n} from '@openid4vc/openid4vci'\nimport type { OpenId4VciCredentialConfigurationSupportedWithFormats, OpenId4VciMetadata } from '../shared'\n\nimport { OpenId4VciCredentialFormatProfile } from '../shared'\nimport { getOid4vcCallbacks } from '../shared/callbacks'\nimport { getOfferedCredentials, getScopesFromCredentialConfigurationsSupported } from '../shared/issuerMetadataUtils'\nimport { getSupportedJwaSignatureAlgorithms } from '../shared/utils'\nimport type {\n  OpenId4VciAcceptCredentialOfferOptions,\n  OpenId4VciAuthCodeFlowOptions,\n  OpenId4VciCredentialBindingResolver,\n  OpenId4VciCredentialResponse,\n  OpenId4VciDeferredCredentialRequestOptions,\n  OpenId4VciDeferredCredentialResponse,\n  OpenId4VciDpopRequestOptions,\n  OpenId4VciProofOfPossessionRequirements,\n  OpenId4VciResolvedAuthorizationRequest,\n  OpenId4VciResolvedCredentialOffer,\n  OpenId4VciRetrieveAuthorizationCodeUsingPresentationOptions,\n  OpenId4VciSendNotificationOptions,\n  OpenId4VciSupportedCredentialFormats,\n  OpenId4VciTokenRefreshOptions,\n  OpenId4VciTokenRequestOptions,\n  OpenId4VcParseAndVerifyAuthorizationResponseOptions,\n} from './OpenId4VciHolderServiceOptions'\nimport { openId4VciSupportedCredentialFormats } from './OpenId4VciHolderServiceOptions'\n\n@injectable()\nexport class OpenId4VciHolderService {\n  private logger: Logger\n  private w3cCredentialService: W3cCredentialService\n  private w3cV2CredentialService: W3cV2CredentialService\n\n  public constructor(\n    @inject(InjectionSymbols.Logger) logger: Logger,\n    w3cCredentialService: W3cCredentialService,\n    w3cV2CredentialService: W3cV2CredentialService\n  ) {\n    this.w3cCredentialService = w3cCredentialService\n    this.w3cV2CredentialService = w3cV2CredentialService\n    this.logger = logger\n  }\n\n  public async resolveIssuerMetadata(\n    agentContext: AgentContext,\n    credentialIssuer: string\n  ): Promise<OpenId4VciMetadata> {\n    const client = this.getClient(agentContext)\n\n    const metadata = await client.resolveIssuerMetadata(credentialIssuer)\n    this.logger.debug('fetched credential issuer metadata', { metadata })\n\n    return metadata\n  }\n\n  public async resolveCredentialOffer(\n    agentContext: AgentContext,\n    credentialOffer: string\n  ): Promise<OpenId4VciResolvedCredentialOffer> {\n    const client = this.getClient(agentContext)\n\n    const credentialOfferObject = await client.resolveCredentialOffer(credentialOffer)\n    const metadata = await client.resolveIssuerMetadata(credentialOfferObject.credential_issuer)\n    this.logger.debug('fetched credential offer and issuer metadata', { metadata, credentialOfferObject })\n\n    const credentialConfigurationsSupported = getOfferedCredentials(\n      credentialOfferObject.credential_configuration_ids,\n      metadata.knownCredentialConfigurations,\n      // We only filter for known configurations, so it's ok if not found\n      { ignoreNotFoundIds: true }\n    )\n\n    return {\n      metadata,\n      offeredCredentialConfigurations: credentialConfigurationsSupported,\n      credentialOfferPayload: credentialOfferObject,\n    }\n  }\n\n  public async resolveAuthorizationRequest(\n    agentContext: AgentContext,\n    resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer,\n    authCodeFlowOptions: OpenId4VciAuthCodeFlowOptions\n  ): Promise<OpenId4VciResolvedAuthorizationRequest> {\n    const { clientId, redirectUri } = authCodeFlowOptions\n    const { metadata, credentialOfferPayload, offeredCredentialConfigurations } = resolvedCredentialOffer\n\n    const oauth2Client = this.getOauth2Client(agentContext)\n    const client = this.getClient(agentContext, {\n      clientId: authCodeFlowOptions.clientId,\n      clientAttestation: authCodeFlowOptions.walletAttestationJwt,\n    })\n\n    // If scope is not provided, we request scope for all offered credentials\n    const scope =\n      authCodeFlowOptions.scope ?? getScopesFromCredentialConfigurationsSupported(offeredCredentialConfigurations)\n\n    if (!credentialOfferPayload.grants?.[authorizationCodeGrantIdentifier]) {\n      throw new CredoError(`Provided credential offer does not include the 'authorization_code' grant.`)\n    }\n\n    const authorizationCodeGrant = credentialOfferPayload.grants[authorizationCodeGrantIdentifier]\n    const authorizationServer = determineAuthorizationServerForCredentialOffer({\n      issuerMetadata: metadata,\n      grantAuthorizationServer: authorizationCodeGrant.authorization_server,\n    })\n\n    const authorizationServerMetadata = getAuthorizationServerMetadataFromList(\n      metadata.authorizationServers,\n      authorizationServer\n    )\n\n    // TODO: should we allow key reuse between dpop and wallet attestation?\n    const isDpopSupported = oauth2Client.isDpopSupported({ authorizationServerMetadata })\n    const dpop = isDpopSupported.supported\n      ? await this.getDpopOptions(agentContext, {\n          dpopSigningAlgValuesSupported: isDpopSupported.dpopSigningAlgValuesSupported,\n        })\n      : undefined\n\n    const authorizationResult = await client.initiateAuthorization({\n      clientId,\n      issuerMetadata: metadata,\n      credentialOffer: credentialOfferPayload,\n      scope: scope.join(' '),\n      redirectUri,\n      dpop,\n    })\n\n    if (authorizationResult.authorizationFlow === AuthorizationFlow.PresentationDuringIssuance) {\n      return {\n        authorizationFlow: AuthorizationFlow.PresentationDuringIssuance,\n        openid4vpRequestUrl: authorizationResult.openid4vpRequestUrl,\n        authSession: authorizationResult.authSession,\n        // FIXME: return dpop result from this endpoint (dpop nonce)\n        dpop: dpop\n          ? {\n              alg: dpop.signer.alg as Kms.KnownJwaSignatureAlgorithm,\n              jwk: Kms.PublicJwk.fromUnknown(dpop.signer.publicJwk),\n            }\n          : undefined,\n      }\n    }\n\n    // Normal Oauth2Redirect flow\n    return {\n      authorizationFlow: AuthorizationFlow.Oauth2Redirect,\n      codeVerifier: authorizationResult.pkce?.codeVerifier,\n      authorizationRequestUrl: authorizationResult.authorizationRequestUrl,\n      // FIXME: return dpop result from this endpoint (dpop nonce)\n      dpop: dpop\n        ? {\n            alg: dpop.signer.alg as Kms.KnownJwaSignatureAlgorithm,\n            jwk: Kms.PublicJwk.fromUnknown(dpop.signer.publicJwk),\n          }\n        : undefined,\n    }\n  }\n\n  public async sendNotification(agentContext: AgentContext, options: OpenId4VciSendNotificationOptions) {\n    const client = this.getClient(agentContext)\n    await client.sendNotification({\n      accessToken: options.accessToken,\n      dpop: options.dpop\n        ? await this.getDpopOptions(agentContext, {\n            ...options.dpop,\n            dpopSigningAlgValuesSupported: [options.dpop.alg],\n          })\n        : undefined,\n      issuerMetadata: options.metadata,\n      notification: {\n        event: options.notificationEvent,\n        notificationId: options.notificationId,\n      },\n    })\n  }\n\n  private async getDpopOptions(\n    agentContext: AgentContext,\n    {\n      jwk,\n      dpopSigningAlgValuesSupported,\n      nonce,\n    }: { dpopSigningAlgValuesSupported: string[]; jwk?: Kms.PublicJwk; nonce?: string }\n  ): Promise<RequestDpopOptions> {\n    const kms = agentContext.resolve(Kms.KeyManagementApi)\n\n    if (jwk) {\n      const alg = dpopSigningAlgValuesSupported.find((alg) =>\n        jwk.supportedSignatureAlgorithms.includes(alg as Kms.KnownJwaSignatureAlgorithm)\n      )\n\n      if (!alg) {\n        throw new CredoError(\n          `No supported dpop signature algorithms found in dpop_signing_alg_values_supported '${dpopSigningAlgValuesSupported.join(\n            ', '\n          )}' matching jwk ${jwk.jwkTypeHumanDescription}`\n        )\n      }\n\n      return {\n        signer: {\n          method: 'jwk',\n          alg,\n          publicJwk: jwk.toJson() as Jwk,\n        },\n        nonce,\n      }\n    }\n\n    const alg = dpopSigningAlgValuesSupported.find((algorithm): algorithm is Kms.KnownJwaSignatureAlgorithm => {\n      try {\n        Kms.PublicJwk.supportedPublicJwkClassForSignatureAlgorithm(algorithm as Kms.KnownJwaSignatureAlgorithm)\n\n        // TODO: we should allow providing allowed backends to OID4VC API so you can limit which\n        // KMS backends can be used for DPOP\n        const supportedBackends = kms.supportedBackendsForOperation({\n          operation: 'sign',\n          algorithm: algorithm as Kms.KnownJwaSignatureAlgorithm,\n        })\n        return supportedBackends.length > 0\n      } catch {\n        return false\n      }\n    })\n\n    if (!alg) {\n      throw new CredoError(\n        `No supported dpop signature algorithms found in dpop_signing_alg_values_supported '${dpopSigningAlgValuesSupported.join(\n          ', '\n        )}'`\n      )\n    }\n\n    const key = await kms.createKeyForSignatureAlgorithm({ algorithm: alg })\n    return {\n      signer: {\n        method: 'jwk',\n        alg,\n        publicJwk: key.publicJwk as Jwk,\n      },\n      nonce,\n    }\n  }\n\n  public async retrieveAuthorizationCodeUsingPresentation(\n    agentContext: AgentContext,\n    options: OpenId4VciRetrieveAuthorizationCodeUsingPresentationOptions\n  ): Promise<{\n    authorizationCode: string\n    dpop?: OpenId4VciDpopRequestOptions\n  }> {\n    const client = this.getClient(agentContext, {\n      clientAttestation: options.walletAttestationJwt,\n    })\n    const dpop = options.dpop\n      ? await this.getDpopOptions(agentContext, {\n          ...options.dpop,\n          dpopSigningAlgValuesSupported: [options.dpop.alg],\n        })\n      : undefined\n\n    const { authorizationChallengeResponse, dpop: dpopResult } =\n      await client.retrieveAuthorizationCodeUsingPresentation({\n        authSession: options.authSession,\n        presentationDuringIssuanceSession: options.presentationDuringIssuanceSession,\n        credentialOffer: options.resolvedCredentialOffer.credentialOfferPayload,\n        issuerMetadata: options.resolvedCredentialOffer.metadata,\n        dpop,\n      })\n\n    return {\n      authorizationCode: authorizationChallengeResponse.authorization_code,\n      dpop: dpop\n        ? {\n            ...dpopResult,\n            alg: dpop.signer.alg as Kms.KnownJwaSignatureAlgorithm,\n            jwk: Kms.PublicJwk.fromUnknown(dpop.signer.publicJwk),\n          }\n        : undefined,\n    }\n  }\n\n  public parseAuthorizationCodeFromAuthorizationResponse(\n    agentContext: AgentContext,\n    options: OpenId4VcParseAndVerifyAuthorizationResponseOptions\n  ) {\n    const { metadata, credentialOfferPayload } = options.resolvedCredentialOffer\n    const client = this.getClient(agentContext)\n\n    const authorizationServer = credentialOfferPayload.grants?.authorization_code?.authorization_server\n    const authorizationServerMetadata = getAuthorizationServerMetadataFromList(\n      metadata.authorizationServers,\n      authorizationServer ?? metadata.authorizationServers[0].issuer\n    )\n\n    const authorizationResponse = client.parseAndVerifyAuthorizationResponseRedirectUrl({\n      authorizationServerMetadata,\n      url: options.authorizationResponseRedirectUrl,\n    })\n\n    if (!authorizationResponse.code) {\n      throw new Oauth2ServerErrorResponseError(authorizationResponse as AuthorizationErrorResponse, {\n        internalMessage: 'Error response received from the authorization server',\n      })\n    }\n\n    return { authorizationCode: authorizationResponse.code }\n  }\n\n  public async requestAccessToken(\n    agentContext: AgentContext,\n    options: OpenId4VciTokenRequestOptions\n  ): Promise<{\n    authorizationServer: string\n    accessTokenResponse: AccessTokenResponse\n    dpop?: OpenId4VciDpopRequestOptions\n  }> {\n    const { metadata, credentialOfferPayload } = options.resolvedCredentialOffer\n    const client = this.getClient(agentContext, {\n      clientAttestation: options.walletAttestationJwt,\n      clientId: 'clientId' in options ? options.clientId : undefined,\n    })\n    const oauth2Client = this.getOauth2Client(agentContext)\n\n    const authorizationServer = options.code\n      ? credentialOfferPayload.grants?.authorization_code?.authorization_server\n      : credentialOfferPayload.grants?.[preAuthorizedCodeGrantIdentifier]?.authorization_server\n    const authorizationServerMetadata = getAuthorizationServerMetadataFromList(\n      metadata.authorizationServers,\n      authorizationServer ?? metadata.authorizationServers[0].issuer\n    )\n\n    const isDpopSupported = oauth2Client.isDpopSupported({\n      authorizationServerMetadata,\n    })\n\n    const dpop = options.dpop\n      ? await this.getDpopOptions(agentContext, {\n          ...options.dpop,\n          dpopSigningAlgValuesSupported: [options.dpop.alg],\n        })\n      : // We should be careful about this case. It could just be the user didn't correctly\n        // provide the DPoP from the auth response. In which case different DPoP will be used\n        // However it might be that they only use DPoP for the token request (esp in pre-auth case)\n        isDpopSupported.supported\n        ? await this.getDpopOptions(agentContext, {\n            dpopSigningAlgValuesSupported: isDpopSupported.dpopSigningAlgValuesSupported,\n          })\n        : undefined\n\n    const result = options.code\n      ? await client.retrieveAuthorizationCodeAccessTokenFromOffer({\n          issuerMetadata: metadata,\n          credentialOffer: credentialOfferPayload,\n          authorizationCode: options.code,\n          dpop,\n          pkceCodeVerifier: options.codeVerifier,\n          redirectUri: options.redirectUri,\n        })\n      : await client.retrievePreAuthorizedCodeAccessTokenFromOffer({\n          credentialOffer: credentialOfferPayload,\n          issuerMetadata: metadata,\n          dpop,\n          txCode: options.txCode,\n        })\n\n    return {\n      ...result,\n      dpop: dpop\n        ? {\n            ...result.dpop,\n            alg: dpop.signer.alg as Kms.KnownJwaSignatureAlgorithm,\n            jwk: Kms.PublicJwk.fromUnknown(dpop.signer.publicJwk),\n          }\n        : undefined,\n    }\n  }\n\n  public async refreshAccessToken(\n    agentContext: AgentContext,\n    options: OpenId4VciTokenRefreshOptions\n  ): Promise<\n    // FIXME: export type in oid4vc library\n    Omit<Awaited<ReturnType<Oauth2Client['retrieveRefreshTokenAccessToken']>>, 'dpop'> & {\n      dpop?: OpenId4VciDpopRequestOptions\n    }\n  > {\n    const oauth2Client = this.getOauth2Client(agentContext, {\n      clientAttestation: options.walletAttestationJwt,\n      clientId: options.clientId,\n    })\n\n    const dpop = options.dpop\n      ? await this.getDpopOptions(agentContext, {\n          ...options.dpop,\n          dpopSigningAlgValuesSupported: [options.dpop.alg],\n        })\n      : undefined\n\n    const authorizationServerMetadata = getAuthorizationServerMetadataFromList(\n      options.issuerMetadata.authorizationServers,\n      options.authorizationServer ?? options.issuerMetadata.authorizationServers[0].issuer\n    )\n\n    const result = await oauth2Client.retrieveRefreshTokenAccessToken({\n      authorizationServerMetadata,\n      refreshToken: options.refreshToken,\n      dpop,\n      resource: options.issuerMetadata.credentialIssuer.credential_issuer,\n    })\n\n    return {\n      ...result,\n      dpop: dpop\n        ? {\n            ...result.dpop,\n            alg: dpop.signer.alg as Kms.KnownJwaSignatureAlgorithm,\n            jwk: Kms.PublicJwk.fromUnknown(dpop.signer.publicJwk),\n          }\n        : undefined,\n    }\n  }\n\n  public async acceptCredentialOffer(\n    agentContext: AgentContext,\n    options: {\n      resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer\n      acceptCredentialOfferOptions: OpenId4VciAcceptCredentialOfferOptions\n      accessToken: string\n      cNonce?: string\n      dpop?: OpenId4VciDpopRequestOptions\n      clientId?: string\n    }\n  ): Promise<{\n    credentials: OpenId4VciCredentialResponse[]\n    deferredCredentials: OpenId4VciDeferredCredentialResponse[]\n    dpop?: OpenId4VciDpopRequestOptions\n    cNonce?: string\n  }> {\n    const { resolvedCredentialOffer, acceptCredentialOfferOptions } = options\n    const { metadata, offeredCredentialConfigurations } = resolvedCredentialOffer\n    const {\n      credentialConfigurationIds,\n      credentialBindingResolver,\n      verifyCredentialStatus,\n      allowedProofOfPossessionSignatureAlgorithms,\n    } = acceptCredentialOfferOptions\n    const client = this.getClient(agentContext)\n\n    if (credentialConfigurationIds?.length === 0) {\n      throw new CredoError(`'credentialConfigurationIds' may not be empty`)\n    }\n\n    const receivedCredentials: Array<OpenId4VciCredentialResponse> = []\n    const deferredCredentials: Array<OpenId4VciDeferredCredentialResponse> = []\n    let cNonce = options.cNonce\n    let dpopNonce = options.dpop?.nonce\n\n    const credentialConfigurationsToRequest =\n      credentialConfigurationIds?.map((id) => {\n        if (!offeredCredentialConfigurations[id]) {\n          const offeredCredentialIds = Object.keys(offeredCredentialConfigurations).join(', ')\n          throw new CredoError(\n            `Credential to request '${id}' is not present in offered credentials. Offered credentials are ${offeredCredentialIds}`\n          )\n        }\n        return [id, offeredCredentialConfigurations[id]] as const\n      }) ?? Object.entries(offeredCredentialConfigurations)\n\n    // If we don't have a nonce yet, we need to first get one\n    if (!cNonce) {\n      // Best option is to use nonce endpoint (draft 14+)\n      if (metadata.credentialIssuer.nonce_endpoint) {\n        const nonceResponse = await client.requestNonce({ issuerMetadata: metadata })\n        cNonce = nonceResponse.c_nonce\n      } else {\n        // Otherwise we will send a dummy request\n        await client\n          .retrieveCredentials({\n            issuerMetadata: metadata,\n            accessToken: options.accessToken,\n            credentialConfigurationId: credentialConfigurationsToRequest[0][0],\n            dpop: options.dpop\n              ? await this.getDpopOptions(agentContext, {\n                  ...options.dpop,\n                  nonce: dpopNonce,\n                  dpopSigningAlgValuesSupported: [options.dpop.alg],\n                })\n              : undefined,\n          })\n          .catch((e) => {\n            if (e instanceof Openid4vciRetrieveCredentialsError && e.response.credentialErrorResponseResult?.success) {\n              cNonce = e.response.credentialErrorResponseResult.data.c_nonce\n            }\n          })\n      }\n    }\n\n    if (!cNonce) {\n      throw new CredoError('No cNonce provided and unable to acquire cNonce from the credential issuer')\n    }\n\n    for (const [offeredCredentialId, offeredCredentialConfiguration] of credentialConfigurationsToRequest) {\n      const { proofs, jwkThumbprintKmsKeyIdMapping } = await this.getCredentialRequestOptions(agentContext, {\n        allowedProofOfPossessionAlgorithms:\n          allowedProofOfPossessionSignatureAlgorithms ?? getSupportedJwaSignatureAlgorithms(agentContext),\n        metadata,\n        offeredCredential: {\n          id: offeredCredentialId,\n          configuration: offeredCredentialConfiguration,\n        },\n        clientId: options.clientId,\n        // We already checked whether nonce exists above\n        cNonce: cNonce as string,\n        credentialBindingResolver,\n      })\n\n      this.logger.debug('Generated credential request proof of possession', { proofs })\n\n      const proof =\n        // Draft 11 ALWAYS uses proof\n        (metadata.originalDraftVersion === Openid4vciVersion.Draft11 ||\n          // Draft 14 allows both proof and proofs. Try to use proof when it makes to improve interoperability\n          (metadata.originalDraftVersion === Openid4vciVersion.Draft14 &&\n            metadata.credentialIssuer.batch_credential_issuance === undefined)) &&\n        proofs.jwt?.length === 1\n          ? ({\n              proof_type: 'jwt',\n              jwt: proofs.jwt[0],\n            } as const)\n          : undefined\n\n      const { credentialResponse, dpop } = await client.retrieveCredentials({\n        issuerMetadata: metadata,\n        accessToken: options.accessToken,\n        credentialConfigurationId: offeredCredentialId,\n        dpop: options.dpop\n          ? await this.getDpopOptions(agentContext, {\n              ...options.dpop,\n              nonce: dpopNonce,\n              dpopSigningAlgValuesSupported: [options.dpop.alg],\n            })\n          : undefined,\n        // Only include proofs if we don't add proof\n        proofs: !proof ? proofs : undefined,\n        proof,\n      })\n\n      // Set new nonce values\n      cNonce = credentialResponse.c_nonce\n      dpopNonce = dpop?.nonce\n\n      if (credentialResponse.transaction_id) {\n        const deferredCredential = {\n          credentialConfigurationId: offeredCredentialId,\n          credentialConfiguration: offeredCredentialConfiguration,\n          transactionId: credentialResponse.transaction_id,\n          interval: credentialResponse.interval,\n          notificationId: credentialResponse.notification_id,\n          jwkThumbprintKmsKeyIdMapping,\n        }\n\n        this.logger.debug('received deferred credential', deferredCredential)\n        deferredCredentials.push(deferredCredential)\n      } else {\n        // Create credential, but we don't store it yet (only after the user has accepted the credential)\n        const credential = await this.handleCredentialResponse(agentContext, credentialResponse, {\n          verifyCredentialStatus: verifyCredentialStatus ?? false,\n          format: offeredCredentialConfiguration.format as OpenId4VciCredentialFormatProfile,\n          credentialConfigurationId: offeredCredentialId,\n          credentialConfiguration: offeredCredentialConfiguration,\n          jwkThumbprintKmsKeyIdMapping,\n        })\n\n        const firstCredential = credential.record.firstCredential\n        this.logger.debug('received credential response', {\n          firstCredential:\n            firstCredential instanceof Mdoc\n              ? {\n                  issuerSignedNamespaces: firstCredential.issuerSignedNamespaces,\n                  base64Url: firstCredential.base64Url,\n                }\n              : firstCredential,\n          totalNumberOfCredentials: credential.record.credentialInstances.length,\n        })\n        receivedCredentials.push(credential)\n      }\n    }\n\n    return {\n      credentials: receivedCredentials,\n      deferredCredentials,\n      dpop: options.dpop\n        ? {\n            ...options.dpop,\n            nonce: dpopNonce,\n          }\n        : undefined,\n      cNonce,\n    }\n  }\n\n  public async retrieveDeferredCredentials(\n    agentContext: AgentContext,\n    options: OpenId4VciDeferredCredentialRequestOptions\n  ): Promise<{\n    credentials: OpenId4VciCredentialResponse[]\n    deferredCredentials: OpenId4VciDeferredCredentialResponse[]\n    dpop?: OpenId4VciDpopRequestOptions\n  }> {\n    const {\n      issuerMetadata,\n      transactionId,\n      credentialConfigurationId,\n      credentialConfiguration,\n      verifyCredentialStatus,\n      accessToken,\n      jwkThumbprintKmsKeyIdMapping,\n    } = options\n    const client = this.getClient(agentContext)\n\n    const receivedCredentials: Array<OpenId4VciCredentialResponse> = []\n    const deferredCredentials: Array<OpenId4VciDeferredCredentialResponse> = []\n    let dpopNonce = options.dpop?.nonce\n\n    const { deferredCredentialResponse, dpop } = await client.retrieveDeferredCredentials({\n      issuerMetadata,\n      accessToken,\n      transactionId,\n      dpop: options.dpop\n        ? await this.getDpopOptions(agentContext, {\n            ...options.dpop,\n            nonce: dpopNonce,\n            dpopSigningAlgValuesSupported: [options.dpop.alg],\n          })\n        : undefined,\n    })\n\n    // Set new nonce values\n    dpopNonce = dpop?.nonce\n\n    if (deferredCredentialResponse.interval) {\n      const deferredCredential: OpenId4VciDeferredCredentialResponse = {\n        credentialConfigurationId,\n        credentialConfiguration,\n        transactionId,\n        interval: deferredCredentialResponse.interval,\n        notificationId: deferredCredentialResponse.notification_id,\n      }\n\n      this.logger.debug('received deferred credential', deferredCredential)\n      deferredCredentials.push(deferredCredential)\n    } else {\n      // Create credential, but we don't store it yet (only after the user has accepted the credential)\n      const credential = await this.handleCredentialResponse(agentContext, deferredCredentialResponse, {\n        verifyCredentialStatus: verifyCredentialStatus ?? false,\n        format: credentialConfiguration.format as OpenId4VciCredentialFormatProfile,\n        credentialConfigurationId: credentialConfigurationId,\n        credentialConfiguration: credentialConfiguration,\n        jwkThumbprintKmsKeyIdMapping,\n      })\n\n      const firstCredential = credential.record.firstCredential\n      this.logger.debug('received credential response', {\n        firstCredential:\n          firstCredential instanceof Mdoc\n            ? {\n                issuerSignedNamespaces: firstCredential.issuerSignedNamespaces,\n                base64Url: firstCredential.base64Url,\n              }\n            : firstCredential,\n        totalNumberOfCredentials: credential.record.credentialInstances.length,\n      })\n      receivedCredentials.push(credential)\n    }\n\n    return {\n      credentials: receivedCredentials,\n      deferredCredentials,\n      dpop: options.dpop\n        ? {\n            ...options.dpop,\n            nonce: dpopNonce,\n          }\n        : undefined,\n    }\n  }\n\n  /**\n   * Get the options for the credential request. Internally this will resolve the proof of possession\n   * requirements, and based on that it will call the proofOfPossessionVerificationMethodResolver to\n   * allow the caller to select the correct verification method based on the requirements for the proof\n   * of possession.\n   */\n  private async getCredentialRequestOptions(\n    agentContext: AgentContext,\n    options: {\n      metadata: OpenId4VciResolvedCredentialOffer['metadata']\n      credentialBindingResolver: OpenId4VciCredentialBindingResolver\n      allowedProofOfPossessionAlgorithms: Kms.KnownJwaSignatureAlgorithm[]\n      clientId?: string\n      cNonce: string\n      offeredCredential: {\n        id: string\n        configuration: OpenId4VciCredentialConfigurationSupportedWithFormats\n      }\n    }\n  ) {\n    const dids = agentContext.resolve(DidsApi)\n    const { allowedProofOfPossessionAlgorithms, offeredCredential } = options\n    const { configuration, id: configurationId } = offeredCredential\n    const supportedJwaSignatureAlgorithms = getSupportedJwaSignatureAlgorithms(agentContext)\n\n    const possibleProofOfPossessionSignatureAlgorithms = allowedProofOfPossessionAlgorithms\n      ? allowedProofOfPossessionAlgorithms.filter((algorithm) => supportedJwaSignatureAlgorithms.includes(algorithm))\n      : supportedJwaSignatureAlgorithms\n\n    if (possibleProofOfPossessionSignatureAlgorithms.length === 0) {\n      throw new CredoError(\n        [\n          'No possible proof of possession signature algorithm found.',\n          `Signature algorithms supported by the Agent '${supportedJwaSignatureAlgorithms.join(', ')}'`,\n          `Allowed Signature algorithms '${allowedProofOfPossessionAlgorithms?.join(', ')}'`,\n        ].join('\\n')\n      )\n    }\n\n    const { proofTypes, supportedDidMethods, supportsAllDidMethods, supportsJwk } =\n      this.getProofOfPossessionRequirements(agentContext, {\n        credentialToRequest: options.offeredCredential,\n        metadata: options.metadata,\n        possibleProofOfPossessionSignatureAlgorithms,\n      })\n\n    const format = configuration.format satisfies `${OpenId4VciSupportedCredentialFormats}`\n    const supportsAnyMethod = supportedDidMethods !== undefined || supportsAllDidMethods || supportsJwk\n    const issuerMaxBatchSize = options.metadata.credentialIssuer.batch_credential_issuance?.batch_size ?? 1\n\n    // Now we need to determine how the credential will be bound to us\n    const credentialBinding = await options.credentialBindingResolver({\n      agentContext,\n      credentialFormat: format as OpenId4VciSupportedCredentialFormats,\n      credentialConfigurationId: configurationId,\n      credentialConfiguration: configuration,\n      metadata: options.metadata,\n      issuerMaxBatchSize,\n      proofTypes,\n      supportsAllDidMethods,\n      supportedDidMethods,\n      supportsJwk,\n      cNonce: options.cNonce,\n    })\n\n    const client = this.getClient(agentContext)\n\n    // Make sure the issuer of proof of possession is valid according to openid issuer metadata\n    if (credentialBinding.method === 'did') {\n      if (!proofTypes.jwt) {\n        throw new CredoError(\n          `JWT proof type is not supported for configuration '${configurationId}', which is required for did based credential binding.`\n        )\n      }\n\n      if (proofTypes.jwt.keyAttestationsRequired) {\n        throw new CredoError(\n          `Credential binding returned list of DID urls, but credential configuration '${configurationId}' requires key attestations. Key attestations and DIDs are not compatible.`\n        )\n      }\n\n      if (credentialBinding.didUrls.length > issuerMaxBatchSize) {\n        throw new CredoError(\n          `Issuer supports issuing a batch of maximum ${issuerMaxBatchSize} credential(s). Binding resolver returned ${credentialBinding.didUrls.length} DID urls. Make sure the returned value does not exceed the max batch issuance.`\n        )\n      }\n\n      if (credentialBinding.didUrls.length === 0) {\n        throw new CredoError('Credential binding with method did returned empty didUrls list')\n      }\n\n      const firstDid = parseDid(credentialBinding.didUrls[0])\n      if (!credentialBinding.didUrls.every((didUrl) => parseDid(didUrl).method === firstDid.method)) {\n        throw new CredoError('Expected all did urls for binding method did to use the same did method')\n      }\n\n      if (\n        !supportsAllDidMethods &&\n        // If supportedDidMethods is undefined, it means the issuer didn't include the binding methods in the metadata\n        // The user can still select a verification method, but we can't validate it\n        supportedDidMethods !== undefined &&\n        !supportedDidMethods.find(\n          (supportedDidMethod) => firstDid.did.startsWith(supportedDidMethod) && supportsAnyMethod\n        )\n      ) {\n        // Test binding method\n        const supportedDidMethodsString = supportedDidMethods.join(', ')\n        throw new CredoError(\n          `Resolved credential binding for proof of possession uses did method '${firstDid.method}', but issuer only supports '${supportedDidMethodsString}'`\n        )\n      }\n\n      // DIDs and mDOC are not compatible\n      if (configuration.format === 'mso_mdoc') {\n        throw new CredoError(\"Using a did for credential binding is not supported for the 'mso_mdoc' format.\")\n      }\n\n      const { publicJwk: firstKey } = await dids.resolveVerificationMethodFromCreatedDidRecord(firstDid.didUrl)\n      const algorithm = proofTypes.jwt.supportedSignatureAlgorithms.find((algorithm) =>\n        firstKey.supportedSignatureAlgorithms.includes(algorithm)\n      )\n      if (!algorithm) {\n        throw new CredoError(\n          `Credential binding returned did url that points to key '${firstKey.jwkTypeHumanDescription}' that supports signature algorithms ${firstKey.supportedSignatureAlgorithms.join(', ')}, but one of '${proofTypes.jwt.supportedSignatureAlgorithms.join(', ')}' was expected`\n        )\n      }\n\n      // This will/should leverage the caching, so it's ok to resolve the did here\n      const keys = await Promise.all(\n        credentialBinding.didUrls.map(async (didUrl, index) =>\n          index === 0\n            ? // We already fetched the first did\n              { jwk: firstKey, didUrl: firstDid.didUrl }\n            : { jwk: (await dids.resolveVerificationMethodFromCreatedDidRecord(didUrl)).publicJwk, didUrl }\n        )\n      )\n      if (!keys.every((key) => Kms.asymmetricJwkKeyTypeMatches(key.jwk.toJson(), firstKey.toJson()))) {\n        throw new CredoError('Expected all did urls to point to the same key type')\n      }\n\n      return {\n        proofs: {\n          jwt: await Promise.all(\n            keys.map((key) =>\n              client\n                .createCredentialRequestJwtProof({\n                  credentialConfigurationId: configurationId,\n                  issuerMetadata: options.metadata,\n                  signer: {\n                    method: 'did',\n                    didUrl: key.didUrl,\n                    alg: algorithm,\n                    kid: key.jwk.keyId,\n                  },\n                  nonce: options.cNonce,\n                  clientId: options.clientId,\n                })\n                .then(({ jwt }) => jwt)\n            )\n          ),\n        },\n      }\n    }\n\n    if (credentialBinding.method === 'jwk') {\n      if (!supportsJwk && supportsAnyMethod) {\n        throw new CredoError(\n          `Resolved credential binding for proof of possession uses jwk, but openid issuer does not support 'jwk' or 'cose_key' cryptographic binding method`\n        )\n      }\n\n      // For W3C credentials (any variant) we only support binding to a DID.\n      if (\n        configuration.format === 'jwt_vc_json' ||\n        configuration.format === 'jwt_vc_json-ld' ||\n        configuration.format === 'ldp_vc' ||\n        (configuration.format === 'vc+sd-jwt' && !configuration.vct)\n      ) {\n        throw new CredoError(\n          `Using a JWK for credential binding is not supported for the '${configuration.format}' format.`\n        )\n      }\n\n      if (!proofTypes.jwt) {\n        throw new CredoError(\n          `JWT proof type is not supported for configuration '${configurationId}', which is required for jwk based credential binding.`\n        )\n      }\n\n      if (proofTypes.jwt.keyAttestationsRequired) {\n        throw new CredoError(\n          `Credential binding returned list of JWK keys, but credential configuration '${configurationId}' requires key attestations. Return a key attestation with binding method 'attestation'.`\n        )\n      }\n\n      if (credentialBinding.keys.length > issuerMaxBatchSize) {\n        throw new CredoError(\n          `Issuer supports issuing a batch of maximum ${issuerMaxBatchSize} credential(s). Binding resolver returned ${credentialBinding.keys.length} keys. Make sure the returned value does not exceed the max batch issuance.`\n        )\n      }\n\n      if (credentialBinding.keys.length === 0) {\n        throw new CredoError('Credential binding with method jwk returned empty keys list')\n      }\n\n      const firstJwk = credentialBinding.keys[0]\n\n      if (!credentialBinding.keys.every((key) => Kms.asymmetricJwkKeyTypeMatches(key.toJson(), firstJwk.toJson()))) {\n        throw new CredoError('Expected all keys for binding method jwk to use the same key type')\n      }\n\n      const algorithm = proofTypes.jwt.supportedSignatureAlgorithms.find((algorithm) =>\n        firstJwk.supportedSignatureAlgorithms.includes(algorithm)\n      )\n      if (!algorithm) {\n        throw new CredoError(\n          `Credential binding returned jwk that points to key '${firstJwk.jwkTypeHumanDescription}' that supports signature algorithms ${firstJwk.supportedSignatureAlgorithms.join(', ')}, but one of '${proofTypes.jwt.supportedSignatureAlgorithms.join(', ')}' was expected`\n        )\n      }\n\n      const jwkThumbprintKmsKeyIdMapping = Object.fromEntries(\n        credentialBinding.keys.map((jwk) => [TypedArrayEncoder.toBase64(jwk.getJwkThumbprint()), jwk.keyId])\n      )\n\n      return {\n        jwkThumbprintKmsKeyIdMapping,\n        proofs: {\n          jwt: await Promise.all(\n            credentialBinding.keys.map((jwk) =>\n              client\n                .createCredentialRequestJwtProof({\n                  credentialConfigurationId: configurationId,\n                  issuerMetadata: options.metadata,\n                  signer: {\n                    method: 'jwk',\n                    publicJwk: jwk.toJson() as Jwk,\n                    alg: algorithm,\n                  },\n                  nonce: options.cNonce,\n                  clientId: options.clientId,\n                })\n                .then(({ jwt }) => jwt)\n            )\n          ),\n        },\n      }\n    }\n\n    if (credentialBinding.method === 'attestation') {\n      const { payload } = parseKeyAttestationJwt({ keyAttestationJwt: credentialBinding.keyAttestationJwt })\n\n      // TODO: check client_id matches in payload\n\n      if (payload.attested_keys.length > issuerMaxBatchSize) {\n        throw new CredoError(\n          `Issuer supports issuing a batch of maximum ${issuerMaxBatchSize} credential(s). Binding resolver returned key attestation with ${payload.attested_keys.length} attested keys. Make sure the returned value does not exceed the max batch issuance.`\n        )\n      }\n\n      // NOTE: for now we require the attested_keys to include the `kid`. If that's not the case\n      // it won't work. We can adjust this later to allow separately providing the jwkThumbprintKmsKeyIdMapping\n      const jwkThumbprintKmsKeyIdMapping = Object.fromEntries(\n        payload.attested_keys.map((jwk) => {\n          const jwkInstance = Kms.PublicJwk.fromUnknown(jwk)\n          return [TypedArrayEncoder.toBase64(jwkInstance.getJwkThumbprint()), jwkInstance.keyId]\n        })\n      )\n\n      // TODO: check nonce matches cNonce. However you could separately fetch the nonce endpoint\n      // (even from another server) when creating the key attestation, so it's maybe too limiting\n      if (proofTypes.attestation && payload.nonce) {\n        // If attestation is supported and the attestation contains a nonce, we can use the attestation directly\n        return {\n          proofs: {\n            attestation: [credentialBinding.keyAttestationJwt],\n          },\n          jwkThumbprintKmsKeyIdMapping,\n        }\n      }\n\n      if (proofTypes.jwt) {\n        // NOTE: the nonce in the key attestation and the jwt proof MUST match, if the key attestation has a nonce.\n        // To prevent errors we use the nonce from the key attestation if present, also for the jwt proof\n        // It might be that during the creation on the key attestation the nonce endpoint was fetched separately.\n        const nonce = payload.nonce ?? options.cNonce\n        const jwk = Kms.PublicJwk.fromUnknown(payload.attested_keys[0])\n\n        return {\n          jwkThumbprintKmsKeyIdMapping,\n          proofs: {\n            jwt: [\n              await client\n                .createCredentialRequestJwtProof({\n                  credentialConfigurationId: configurationId,\n                  issuerMetadata: options.metadata,\n                  signer: {\n                    method: 'jwk',\n                    publicJwk: payload.attested_keys[0],\n                    // TODO: we should probably use the 'alg' from the jwk\n                    alg: jwk.supportedSignatureAlgorithms[0],\n                  },\n                  keyAttestationJwt: credentialBinding.keyAttestationJwt,\n                  nonce,\n                  clientId: options.clientId,\n                })\n                .then(({ jwt }) => jwt),\n            ],\n          },\n        }\n      }\n\n      throw new CredoError(\n        `Unable to create credential request proofs. Configuration supports 'attestation' proof type, but attestation did not contain a 'nonce' value`\n      )\n    }\n\n    // @ts-expect-error currently if/else if exhaustive, but once we add new option it will give ts error\n    throw new CredoError(`Unsupported credential binding method ${credentialBinding.method}`)\n  }\n\n  /**\n   * Get the requirements for creating the proof of possession. Based on the allowed\n   * credential formats, the allowed proof of possession signature algorithms, and the\n   * credential type, this method will select the best credential format and signature\n   * algorithm to use, based on the order of preference.\n   */\n  private getProofOfPossessionRequirements(\n    agentContext: AgentContext,\n    options: {\n      metadata: IssuerMetadataResult\n      credentialToRequest: {\n        id: string\n        configuration: OpenId4VciCredentialConfigurationSupportedWithFormats\n      }\n      possibleProofOfPossessionSignatureAlgorithms: Kms.KnownJwaSignatureAlgorithm[]\n    }\n  ): OpenId4VciProofOfPossessionRequirements {\n    const { credentialToRequest, possibleProofOfPossessionSignatureAlgorithms, metadata } = options\n    const { configuration, id: configurationId } = credentialToRequest\n\n    if (!openId4VciSupportedCredentialFormats.includes(configuration.format as OpenId4VciSupportedCredentialFormats)) {\n      throw new CredoError(\n        [\n          `Requested credential with format '${credentialToRequest.configuration.format}',`,\n          `for the credential with id '${credentialToRequest.id},`,\n          `but the wallet only supports the following formats '${openId4VciSupportedCredentialFormats.join(', ')}'`,\n        ].join('\\n')\n      )\n    }\n\n    // For each of the supported algs, find the key types, then find the proof types\n    const signatureSuiteRegistry = agentContext.dependencyManager.resolve(SignatureSuiteRegistry)\n\n    let proofTypesSupported = configuration.proof_types_supported\n    if (!proofTypesSupported) {\n      // For draft above 11 we do not allow no proof_type (we do not support no key binding for now)\n      if (metadata.originalDraftVersion !== Openid4vciVersion.Draft11) {\n        throw new CredoError(\n          `Credential configuration '${configurationId}' does not specify proof_types_supported. Credentials not bound to keys are not supported at the moment`\n        )\n      }\n\n      // For draft 11 we fall back to jwt proof type\n      proofTypesSupported = {\n        jwt: {\n          proof_signing_alg_values_supported: possibleProofOfPossessionSignatureAlgorithms,\n        },\n      }\n    }\n\n    const proofTypes: OpenId4VciProofOfPossessionRequirements['proofTypes'] = {\n      jwt: undefined,\n      attestation: undefined,\n    }\n\n    for (const [proofType, proofTypeConfig] of Object.entries(proofTypesSupported)) {\n      if (proofType !== 'jwt' && proofType !== 'attestation') continue\n\n      let signatureAlgorithms: Kms.KnownJwaSignatureAlgorithm[] = []\n\n      const proofSigningAlgsSupported = proofTypeConfig?.proof_signing_alg_values_supported\n      if (proofSigningAlgsSupported === undefined) {\n        // If undefined, it means the issuer didn't include the cryptographic suites in the metadata\n        // We just guess that the first one is supported\n        signatureAlgorithms = options.possibleProofOfPossessionSignatureAlgorithms\n      } else {\n        switch (credentialToRequest.configuration.format) {\n          case OpenId4VciCredentialFormatProfile.JwtVcJson:\n          case OpenId4VciCredentialFormatProfile.JwtVcJsonLd:\n          case OpenId4VciCredentialFormatProfile.SdJwtVc:\n          case OpenId4VciCredentialFormatProfile.SdJwtDc:\n          case OpenId4VciCredentialFormatProfile.MsoMdoc:\n            signatureAlgorithms = options.possibleProofOfPossessionSignatureAlgorithms.filter((signatureAlgorithm) =>\n              proofSigningAlgsSupported.includes(signatureAlgorithm)\n            )\n            break\n          // FIXME: this is wrong, as the proof type is separate from the credential signing alg\n          // But there might be some draft 11 logic that depends on this, can be removed soon\n          case OpenId4VciCredentialFormatProfile.LdpVc:\n            signatureAlgorithms = options.possibleProofOfPossessionSignatureAlgorithms.filter((signatureAlgorithm) => {\n              try {\n                const jwkClass = Kms.PublicJwk.supportedPublicJwkClassForSignatureAlgorithm(signatureAlgorithm)\n                const matchingSuites = signatureSuiteRegistry.getAllByPublicJwkType(jwkClass)\n                if (matchingSuites.length === 0) return false\n\n                return proofSigningAlgsSupported.includes(matchingSuites[0].proofType)\n              } catch {\n                return false\n              }\n            })\n            break\n          default:\n            throw new CredoError('Unsupported credential format.')\n        }\n      }\n\n      proofTypes[proofType] = {\n        supportedSignatureAlgorithms: signatureAlgorithms,\n        keyAttestationsRequired: proofTypeConfig.key_attestations_required\n          ? {\n              keyStorage: proofTypeConfig.key_attestations_required.key_storage,\n              userAuthentication: proofTypeConfig.key_attestations_required.user_authentication,\n            }\n          : undefined,\n      }\n    }\n\n    const { jwt, attestation } = proofTypes\n    if (!jwt && !attestation) {\n      const supported = Object.keys(proofTypesSupported).join(', ')\n      throw new CredoError(`Unsupported proof type(s) ${supported}. Supported proof type(s) are: jwt, attestation`)\n    }\n\n    const issuerSupportedBindingMethods = credentialToRequest.configuration.cryptographic_binding_methods_supported\n    const supportsAllDidMethods = issuerSupportedBindingMethods?.includes('did') ?? false\n    const supportedDidMethods = issuerSupportedBindingMethods?.filter((method) => method.startsWith('did:'))\n\n    // The cryptographic_binding_methods_supported describe the cryptographic key material that the issued Credential is bound to.\n    const supportsCoseKey = issuerSupportedBindingMethods?.includes('cose_key') ?? false\n    const supportsJwk = issuerSupportedBindingMethods?.includes('jwk') || supportsCoseKey\n\n    return {\n      proofTypes,\n      supportedDidMethods,\n      supportsAllDidMethods,\n      supportsJwk,\n    }\n  }\n\n  private async handleCredentialResponse(\n    agentContext: AgentContext,\n    credentialResponse: CredentialResponse | DeferredCredentialResponse,\n    options: {\n      verifyCredentialStatus: boolean\n      format: OpenId4VciCredentialFormatProfile\n      credentialConfigurationId: string\n      credentialConfiguration: OpenId4VciCredentialConfigurationSupportedWithFormats\n      jwkThumbprintKmsKeyIdMapping?: Record<string, string>\n    }\n  ): Promise<OpenId4VciCredentialResponse> {\n    const { verifyCredentialStatus, credentialConfigurationId, credentialConfiguration } = options\n    this.logger.debug('Credential response', credentialResponse)\n\n    const credentials = credentialResponse.credentials\n      ? credentialResponse.credentials.every((c) => typeof c === 'object' && c !== null && 'credential' in c)\n        ? credentialResponse.credentials.map((c) => (c as { credential: string | Record<string, unknown> }).credential)\n        : (credentialResponse.credentials as (string | Record<string, unknown>)[])\n      : credentialResponse.credential\n        ? [credentialResponse.credential as CredentialResponse['credential']]\n        : undefined\n\n    if (!credentials) {\n      throw new CredoError(`Credential response returned neither 'credentials' nor 'credential' parameter.`)\n    }\n\n    const notificationId = credentialResponse.notification_id\n\n    const format = options.format\n    if (format === OpenId4VciCredentialFormatProfile.SdJwtVc || format === OpenId4VciCredentialFormatProfile.SdJwtDc) {\n      if (!credentials.every((c) => typeof c === 'string')) {\n        throw new CredoError(\n          `Received credential(s) of format ${format}, but not all credential(s) are a string. ${JSON.stringify(\n            credentials\n          )}`\n        )\n      }\n      // FIXME: we need to link the credential bound key back to the credential request\n      // so we can store the correct `kmsKeyId` along with the SD-JWT VC for presentations\n      if (format === OpenId4VciCredentialFormatProfile.SdJwtDc || credentialConfiguration.vct) {\n        const sdJwtVcApi = agentContext.dependencyManager.resolve(SdJwtVcApi)\n        const verificationResults = await Promise.all(\n          credentials.map(async (compactSdJwtVc, index) => {\n            const result = await sdJwtVcApi.verify({\n              compactSdJwtVc,\n              // Only load and verify it for the first instance\n              fetchTypeMetadata: index === 0,\n            })\n\n            // Link key id with credential\n            if (result.sdJwtVc?.holder?.method === 'jwk') {\n              const jwkThumbprint = TypedArrayEncoder.toBase64(result.sdJwtVc.holder.jwk.getJwkThumbprint())\n              const kmsKeyId = options.jwkThumbprintKmsKeyIdMapping?.[jwkThumbprint]\n              if (!kmsKeyId) {\n                throw new CredoError(\n                  `Missing kmsKeyId for jwk with thumbprint ${jwkThumbprint}. A credential was issued for a key that was not in the credential request.`\n                )\n              }\n\n              result.sdJwtVc.kmsKeyId = kmsKeyId\n            }\n\n            return result\n          })\n        )\n\n        if (!verificationResults.every((result) => result.isValid)) {\n          agentContext.config.logger.error('Failed to validate credential(s)', { verificationResults })\n          throw new CredoError(\n            `Failed to validate sd-jwt-vc credentials. Results = ${JSON.stringify(verificationResults, replaceError)}`\n          )\n        }\n\n        return {\n          record: new SdJwtVcRecord({\n            credentialInstances: verificationResults.map((r) => ({\n              compactSdJwtVc: r.sdJwtVc.compact,\n              kmsKeyId: r.sdJwtVc.kmsKeyId,\n            })) as SdJwtVcRecordInstances,\n            typeMetadata: verificationResults[0].sdJwtVc.typeMetadata,\n            typeMetadataChain: verificationResults[0].typeMetadataChain,\n          }),\n          notificationId,\n          credentialConfigurationId,\n          credentialConfiguration,\n        }\n      }\n\n      const result = await Promise.all(\n        credentials.map(async (c) => {\n          const credential = W3cV2SdJwtVerifiableCredential.fromCompact(c)\n          const result = await this.w3cV2CredentialService.verifyCredential(agentContext, {\n            credential,\n          })\n\n          return { credential, result }\n        })\n      )\n\n      if (!result.every((c) => c.result.isValid)) {\n        agentContext.config.logger.error('Failed to validate credentials', { result })\n        throw new CredoError(\n          `Failed to validate credential, error = ${result\n            .map((e) => e.result.error?.message)\n            .filter(Boolean)\n            .join(', ')}`\n        )\n      }\n\n      return {\n        record: new W3cV2CredentialRecord({\n          credentialInstances: result.map((r) => ({\n            credential: r.credential.encoded,\n          })) as W3cV2CredentialRecordInstances,\n        }),\n        notificationId,\n        credentialConfigurationId,\n        credentialConfiguration,\n      }\n    }\n\n    if (\n      options.format === OpenId4VciCredentialFormatProfile.JwtVcJson ||\n      options.format === OpenId4VciCredentialFormatProfile.JwtVcJsonLd\n    ) {\n      if (!credentials.every((c) => typeof c === 'string')) {\n        throw new CredoError(\n          `Received credential(s) of format ${format}, but not all credential(s) are a string. ${JSON.stringify(\n            credentials\n          )}`\n        )\n      }\n\n      const result = await Promise.all(\n        credentials.map(async (c) => {\n          const credential = W3cJwtVerifiableCredential.fromSerializedJwt(c)\n          const result = await this.w3cCredentialService.verifyCredential(agentContext, {\n            credential,\n            verifyCredentialStatus,\n          })\n\n          return { credential, result }\n        })\n      )\n\n      if (!result.every((c) => c.result.isValid)) {\n        agentContext.config.logger.error('Failed to validate credentials', { result })\n        throw new CredoError(\n          `Failed to validate credential, error = ${result\n            .map((e) => e.result.error?.message)\n            .filter(Boolean)\n            .join(', ')}`\n        )\n      }\n\n      return {\n        record: new W3cCredentialRecord({\n          credentialInstances: result.map((r) => ({\n            credential: r.credential.encoded,\n          })) as W3cCredentialRecordInstances,\n          tags: {},\n        }),\n        notificationId,\n        credentialConfigurationId,\n        credentialConfiguration,\n      }\n    }\n\n    if (format === OpenId4VciCredentialFormatProfile.LdpVc) {\n      if (!credentials.every((c) => typeof c === 'object' && c !== null)) {\n        throw new CredoError(\n          `Received credential(s) of format ${format}, but not all credential(s) are an object. ${JSON.stringify(\n            credentials\n          )}`\n        )\n      }\n      const result = await Promise.all(\n        credentials.map(async (c) => {\n          const credential = W3cJsonLdVerifiableCredential.fromJson(c)\n          const result = await this.w3cCredentialService.verifyCredential(agentContext, {\n            credential,\n            verifyCredentialStatus,\n          })\n\n          return { credential, result }\n        })\n      )\n\n      if (!result.every((c) => c.result.isValid)) {\n        agentContext.config.logger.error('Failed to validate credentials', { result })\n        throw new CredoError(\n          `Failed to validate credential, error = ${result\n            .map((e) => e.result.error?.message)\n            .filter(Boolean)\n            .join(', ')}`\n        )\n      }\n\n      const w3cJsonLdCredentialService = agentContext.resolve(W3cJsonLdCredentialService)\n      return {\n        record: new W3cCredentialRecord({\n          credentialInstances: result.map((r) => ({\n            credential: r.credential.encoded,\n          })) as W3cCredentialRecordInstances,\n          tags: {\n            // Fetch it directly\n            expandedTypes: await w3cJsonLdCredentialService.getExpandedTypesForCredential(\n              agentContext,\n              result[0].credential\n            ),\n          },\n        }),\n        notificationId,\n        credentialConfigurationId,\n        credentialConfiguration,\n      }\n    }\n\n    if (format === OpenId4VciCredentialFormatProfile.MsoMdoc) {\n      if (!credentials.every((c) => typeof c === 'string')) {\n        throw new CredoError(\n          `Received credential(s) of format ${format}, but not all credential(s) are a string. ${JSON.stringify(\n            credentials\n          )}`\n        )\n      }\n      const mdocApi = agentContext.dependencyManager.resolve(MdocApi)\n      const result = await Promise.all(\n        credentials.map(async (credential) => {\n          const mdoc = Mdoc.fromBase64Url(credential)\n          const result = await mdocApi.verify(mdoc, {})\n\n          const jwkThumbprint = TypedArrayEncoder.toBase64(mdoc.deviceKey.getJwkThumbprint())\n          const kmsKeyId = options.jwkThumbprintKmsKeyIdMapping?.[jwkThumbprint]\n          if (!kmsKeyId) {\n            throw new CredoError(\n              `Missing kmsKeyId for jwk with thumbprint ${jwkThumbprint}. A credential was issued for a key that was not in the credential request.`\n            )\n          }\n\n          mdoc.deviceKeyId = kmsKeyId\n          return {\n            result,\n            mdoc,\n          }\n        })\n      )\n\n      if (!result.every((r) => r.result.isValid)) {\n        agentContext.config.logger.error('Failed to validate credentials', { result })\n        throw new CredoError(\n          `Failed to validate mdoc credential(s). \\n - ${result\n            .map((r, i) => (r.result.isValid ? undefined : `(${i}) ${r.result.error}`))\n            .filter(Boolean)\n            .join('\\n - ')}`\n        )\n      }\n\n      return {\n        record: new MdocRecord({\n          credentialInstances: result.map((c) => ({\n            issuerSignedBase64Url: c.mdoc.base64Url,\n            kmsKeyId: c.mdoc.deviceKeyId,\n          })) as MdocRecordInstances,\n        }),\n        notificationId,\n        credentialConfigurationId,\n        credentialConfiguration,\n      }\n    }\n\n    throw new CredoError(`Unsupported credential format ${options.format}`)\n  }\n\n  private getCallbacks(\n    agentContext: AgentContext,\n    { clientAttestation, clientId }: { clientAttestation?: string; clientId?: string } = {}\n  ) {\n    const callbacks = getOid4vcCallbacks(agentContext)\n\n    return {\n      ...callbacks,\n      clientAuthentication: (options) => {\n        const { authorizationServerMetadata, url, body } = options\n        const oauth2Client = this.getOauth2Client(agentContext)\n        const clientAttestationSupported = oauth2Client.isClientAttestationSupported({\n          authorizationServerMetadata,\n        })\n\n        // Client attestations\n        if (clientAttestation && clientAttestationSupported) {\n          return clientAuthenticationClientAttestationJwt({\n            clientAttestationJwt: clientAttestation,\n            callbacks,\n          })(options)\n        }\n\n        // Pre auth flow\n        if (\n          url === authorizationServerMetadata.token_endpoint &&\n          authorizationServerMetadata['pre-authorized_grant_anonymous_access_supported'] &&\n          body.grant_type === preAuthorizedCodeGrantIdentifier\n        ) {\n          return clientAuthenticationAnonymous()(options)\n        }\n\n        // Just a client id (no auth)\n        if (clientId) {\n          return clientAuthenticationNone({ clientId })(options)\n        }\n\n        // NOTE: we fall back to anonymous authentication for pre-auth for now, as there's quite some\n        // issuers that do not have pre-authorized_grant_anonymous_access_supported defined\n        if (\n          url === authorizationServerMetadata.token_endpoint &&\n          body.grant_type === preAuthorizedCodeGrantIdentifier\n        ) {\n          return clientAuthenticationAnonymous()(options)\n        }\n\n        // Refresh token flow defaults to anonymous auth if there is neither a client attestation or client id\n        // is present.\n        if (body.grant_type === refreshTokenGrantIdentifier) {\n          return clientAuthenticationAnonymous()(options)\n        }\n\n        // TODO: We should still look at auth_methods_supported\n        // If there is an auth session for the auth challenge endpoint, we don't have to include the client_id\n        if (url === authorizationServerMetadata.authorization_challenge_endpoint && body.auth_session) {\n          return clientAuthenticationAnonymous()(options)\n        }\n\n        throw new CredoError('Unable to perform client authentication.')\n      },\n    } satisfies Partial<CallbackContext>\n  }\n\n  private getClient(agentContext: AgentContext, options: { clientAttestation?: string; clientId?: string } = {}) {\n    return new Openid4vciClient({\n      callbacks: this.getCallbacks(agentContext, options),\n    })\n  }\n\n  private getOauth2Client(agentContext: AgentContext, options?: { clientAttestation?: string; clientId?: string }) {\n    return new Oauth2Client({\n      callbacks: options ? this.getCallbacks(agentContext, options) : getOid4vcCallbacks(agentContext),\n    })\n  }\n}\n"],"mappings":"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"}