@credo-ts/openid4vc 0.6.2-alpha-20251222120740 → 0.6.2-pr-2610-20260107224024
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.d.mts +2 -2
- package/build/openid4vc-holder/OpenId4VcHolderApi.d.mts +4 -1
- package/build/openid4vc-holder/OpenId4VcHolderApi.d.mts.map +1 -1
- package/build/openid4vc-holder/OpenId4VcHolderApi.mjs +3 -0
- package/build/openid4vc-holder/OpenId4VcHolderApi.mjs.map +1 -1
- package/build/openid4vc-holder/OpenId4VciHolderService.d.mts +4 -1
- package/build/openid4vc-holder/OpenId4VciHolderService.d.mts.map +1 -1
- package/build/openid4vc-holder/OpenId4VciHolderService.mjs +16 -4
- package/build/openid4vc-holder/OpenId4VciHolderService.mjs.map +1 -1
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.d.mts +5 -1
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.d.mts.map +1 -1
- package/build/openid4vc-holder/OpenId4VciHolderServiceOptions.mjs.map +1 -1
- package/build/openid4vc-holder/index.d.mts +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.d.mts +2 -0
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.d.mts.map +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerService.d.mts +4 -3
- package/build/openid4vc-issuer/OpenId4VcIssuerService.d.mts.map +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerService.mjs +5 -4
- package/build/openid4vc-issuer/OpenId4VcIssuerService.mjs.map +1 -1
- package/build/openid4vc-issuer/router/credentialEndpoint.mjs +2 -2
- package/build/openid4vc-issuer/router/credentialEndpoint.mjs.map +1 -1
- package/build/openid4vc-issuer/router/redirectEndpoint.mjs +12 -4
- package/build/openid4vc-issuer/router/redirectEndpoint.mjs.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenId4VciHolderService.mjs","names":["OpenId4VciHolderService","logger: Logger","alg","receivedCredentials: Array<OpenId4VciCredentialResponse>","deferredCredentials: Array<OpenId4VciDeferredCredentialResponse>","deferredCredential: OpenId4VciDeferredCredentialResponse","algorithm","proofTypes: OpenId4VciProofOfPossessionRequirements['proofTypes']","signatureAlgorithms: Kms.KnownJwaSignatureAlgorithm[]","result"],"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 authorizationCodeGrantIdentifier,\n type CallbackContext,\n clientAuthenticationAnonymous,\n clientAuthenticationClientAttestationJwt,\n clientAuthenticationNone,\n getAuthorizationServerMetadataFromList,\n type Jwk,\n Oauth2Client,\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 Openid4vciDraftVersion,\n Openid4vciRetrieveCredentialsError,\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} 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 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 === Openid4vciDraftVersion.Draft11 ||\n // Draft 14 allows both proof and proofs. Try to use proof when it makes to improve interoperability\n (metadata.originalDraftVersion === Openid4vciDraftVersion.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.assymetricJwkKeyTypeMatches(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.assymetricJwkKeyTypeMatches(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 !== Openid4vciDraftVersion.Draft11) {\n throw new CredoError(\n `Credential configuration '${configurationId}' does not specifcy 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 }),\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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"}
|
|
1
|
+
{"version":3,"file":"OpenId4VciHolderService.mjs","names":["OpenId4VciHolderService","logger: Logger","alg","receivedCredentials: Array<OpenId4VciCredentialResponse>","deferredCredentials: Array<OpenId4VciDeferredCredentialResponse>","deferredCredential: OpenId4VciDeferredCredentialResponse","algorithm","proofTypes: OpenId4VciProofOfPossessionRequirements['proofTypes']","signatureAlgorithms: Kms.KnownJwaSignatureAlgorithm[]","result"],"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.assymetricJwkKeyTypeMatches(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.assymetricJwkKeyTypeMatches(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 }),\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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"}
|
|
@@ -97,6 +97,10 @@ interface OpenId4VciSendNotificationOptions {
|
|
|
97
97
|
notificationEvent: OpenId4VciNotificationEvent;
|
|
98
98
|
dpop?: OpenId4VciDpopRequestOptions;
|
|
99
99
|
}
|
|
100
|
+
interface OpenId4VcParseAndVerifyAuthorizationResponseOptions {
|
|
101
|
+
authorizationResponseRedirectUrl: string;
|
|
102
|
+
resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer;
|
|
103
|
+
}
|
|
100
104
|
interface OpenId4VcAuthorizationCodeTokenRequestOptions {
|
|
101
105
|
resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer;
|
|
102
106
|
code: string;
|
|
@@ -394,5 +398,5 @@ interface OpenId4VciProofOfPossessionRequirements {
|
|
|
394
398
|
supportsJwk: boolean;
|
|
395
399
|
}
|
|
396
400
|
//#endregion
|
|
397
|
-
export { OpenId4VcAuthorizationCodeTokenRequestOptions, OpenId4VciAcceptCredentialOfferOptions, OpenId4VciAuthCodeFlowOptions, OpenId4VciAuthorizationFlow, OpenId4VciCredentialBindingOptions, OpenId4VciCredentialBindingResolver, OpenId4VciCredentialRequestOptions, OpenId4VciCredentialResponse, OpenId4VciDeferredCredentialRequestOptions, OpenId4VciDeferredCredentialResponse, OpenId4VciDpopRequestOptions, OpenId4VciNotificationEvent, OpenId4VciPreAuthorizedTokenRequestOptions, OpenId4VciProofOfPossessionRequirements, OpenId4VciProofOfPressionProofTypes, OpenId4VciRequestTokenResponse, OpenId4VciResolvedAuthorizationRequest, OpenId4VciResolvedCredentialOffer, OpenId4VciRetrieveAuthorizationCodeUsingPresentationOptions, OpenId4VciSendNotificationOptions, OpenId4VciSupportedCredentialFormats, OpenId4VciTokenRefreshOptions, OpenId4VciTokenRequestOptions, openId4VciSupportedCredentialFormats };
|
|
401
|
+
export { OpenId4VcAuthorizationCodeTokenRequestOptions, OpenId4VcParseAndVerifyAuthorizationResponseOptions, OpenId4VciAcceptCredentialOfferOptions, OpenId4VciAuthCodeFlowOptions, OpenId4VciAuthorizationFlow, OpenId4VciCredentialBindingOptions, OpenId4VciCredentialBindingResolver, OpenId4VciCredentialRequestOptions, OpenId4VciCredentialResponse, OpenId4VciDeferredCredentialRequestOptions, OpenId4VciDeferredCredentialResponse, OpenId4VciDpopRequestOptions, OpenId4VciNotificationEvent, OpenId4VciPreAuthorizedTokenRequestOptions, OpenId4VciProofOfPossessionRequirements, OpenId4VciProofOfPressionProofTypes, OpenId4VciRequestTokenResponse, OpenId4VciResolvedAuthorizationRequest, OpenId4VciResolvedCredentialOffer, OpenId4VciRetrieveAuthorizationCodeUsingPresentationOptions, OpenId4VciSendNotificationOptions, OpenId4VciSupportedCredentialFormats, OpenId4VciTokenRefreshOptions, OpenId4VciTokenRequestOptions, openId4VciSupportedCredentialFormats };
|
|
398
402
|
//# sourceMappingURL=OpenId4VciHolderServiceOptions.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenId4VciHolderServiceOptions.d.mts","names":[],"sources":["../../src/openid4vc-holder/OpenId4VciHolderServiceOptions.ts"],"sourcesContent":[],"mappings":";;;;;;;;KAqBY,oCAAA,GACR,iCAAA,CAAkC,YAClC,iCAAA,CAAkC,cAClC,iCAAA,CAAkC,UAClC,iCAAA,CAAkC,UAClC,iCAAA,CAAkC,QAClC,iCAAA,CAAkC;cAEzB,sCAAsC;AARvC,UAiBK,4BAAA,CAjB+B;EAC5C,GAAA,EAiBG,GAAA,CAAI,SAjBP;EACA,GAAA,EAiBG,GAAA,CAAI,0BAjB2B;EAClC,KAAA,CAAA,EAAA,MAAA;;;;;AAKJ;AASA;AAWY,KAAA,2BAAA,GAA2B,qBAAA,GAAA,oBAAA,GAAA,oBAAA;AAE3B,KAAA,8BAAA,GAA8B;EAUzB,WAAA,EAAA,MAAA;EAEU,YAAA,CAAA,EAAA,MAAA;EAWjB,MAAA,CAAA,EAAA,MAAA;EAAgB,IAAA,CAAA,EAnBjB,4BAmBiB;EAAa,mBAAA,CAAA,EAAA,MAAA;EAAsB,mBAAA,EAhBtC,6BAgBsC;CAAqB;AAKjE,UAlBA,4BAAA,CAkBoC;EAcpC,yBAAA,EAAA,MAAA;EACL,uBAAA,EA/Be,qDA+Bf;EACc;;;AAQ1B;;;;;;EAsBiB,MAAA,EAnDP,aAmDO,GAnDS,UAmDT,GAnDsB,mBAmDW,GAnDW,qBAmDX;EACtC,cAAA,CAAA,EAAA,MAAA;;AAkBH,UAjEQ,oCAAA,CAiER;EAA4B,yBAAA,EAAA,MAAA;EAGpB,uBAAA,EAlEU,
|
|
1
|
+
{"version":3,"file":"OpenId4VciHolderServiceOptions.d.mts","names":[],"sources":["../../src/openid4vc-holder/OpenId4VciHolderServiceOptions.ts"],"sourcesContent":[],"mappings":";;;;;;;;KAqBY,oCAAA,GACR,iCAAA,CAAkC,YAClC,iCAAA,CAAkC,cAClC,iCAAA,CAAkC,UAClC,iCAAA,CAAkC,UAClC,iCAAA,CAAkC,QAClC,iCAAA,CAAkC;cAEzB,sCAAsC;AARvC,UAiBK,4BAAA,CAjB+B;EAC5C,GAAA,EAiBG,GAAA,CAAI,SAjBP;EACA,GAAA,EAiBG,GAAA,CAAI,0BAjB2B;EAClC,KAAA,CAAA,EAAA,MAAA;;;;;AAKJ;AASA;AAWY,KAAA,2BAAA,GAA2B,qBAAA,GAAA,oBAAA,GAAA,oBAAA;AAE3B,KAAA,8BAAA,GAA8B;EAUzB,WAAA,EAAA,MAAA;EAEU,YAAA,CAAA,EAAA,MAAA;EAWjB,MAAA,CAAA,EAAA,MAAA;EAAgB,IAAA,CAAA,EAnBjB,4BAmBiB;EAAa,mBAAA,CAAA,EAAA,MAAA;EAAsB,mBAAA,EAhBtC,6BAgBsC;CAAqB;AAKjE,UAlBA,4BAAA,CAkBoC;EAcpC,yBAAA,EAAA,MAAA;EACL,uBAAA,EA/Be,qDA+Bf;EACc;;;AAQ1B;;;;;;EAsBiB,MAAA,EAnDP,aAmDO,GAnDS,UAmDT,GAnDsB,mBAmDW,GAnDW,qBAmDX;EACtC,cAAA,CAAA,EAAA,MAAA;;AAkBH,UAjEQ,oCAAA,CAiER;EAA4B,yBAAA,EAAA,MAAA;EAGpB,uBAAA,EAlEU,qDAoEA;EAGV,aAAA,EAAA,MAAA;EA6BA,QAAA,CAAA,EAAA,MAAA;EAqBL,cAAA,CAAA,EAAA,MAAA;EAIA;AAkCZ;AAyBA;;;EAIS,4BAAA,CAAA,EAnLwB,MAmLxB,CAAA,MAAA,EAAA,MAAA,CAAA;;AAJuD,UA5K/C,iCAAA,CA4K+C;EAgB/C,QAAA,EA3LL,oBA2LK;EA2CA,sBAAA,EArOS,qBAqOiC;EACzC;;;EAae,+BAAA,EA9OE,sDA8OF;;AAMhB,KAjPL,sCAAA,GAiPkC;EAgB7B,mBAAA,EAAA,MAAA;EACD,iBAAA,EA/PS,2BAAA,CAA4B,0BA+PrC;EAMJ,WAAA,EAAA,MAAA;EAMQ;;;EAyB4D,IAAA,CAAA,EA9RnE,4BA8RmE;AAyDhF,CAAA,GAAY;EACD,uBAAA,EAAA,MAAA;EACE,iBAAA,EArVY,2BAAA,CAA4B,cAqVxC;EAAR,YAAA,CAAA,EAAA,MAAA;EAA4C;;AAEjD;EAoCiB,IAAA,CAAA,EArXJ,4BAqXI;;UAlXA,iCAAA;YACL;;;;;;;;;;;;;qBAgBS;SAEZ;;UAGQ,mDAAA;;2BAEU;;UAGV,6CAAA;2BACU;;;;;;;;;;;;SAclB;;;;;;;;;;;UAcQ,0CAAA;2BACU;;;;;;SAQlB;;;;;;;;;;KAYG,6BAAA,GACR,6CACA;KAEQ,6BAAA;;;;;kBAMM;;;;;;;;SAUT;;;;;;;;;;;;;;;UAkBQ,2DAAA;2BACU;SAClB;;;;;;;;;;;;;;;;;;;UAuBQ,kCAAA,SAA2C,KAAK;2BACtC;;;SAGlB;;;;;;;;;;UAYQ,sCAAA;;;;;;;;;;;;;;;;;;;;gDAsB+B,GAAA,CAAI;;;;;;;;;;;;;;6BAevB;;;;;UAMZ,0CAAA;kBACC;;;2BAGS;;;SAGlB;;;;;;iCAOwB;;;;;UAMhB,6BAAA;;;;;;;;;;;;;UAgBA,kCAAA;gBACD;;;;;YAMJ;;;;;oBAMQ;;;;;;;;;;;;;cAeN;;;;;;;;2BAUa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAyDf,mCAAA,aACD,uCACN,QAAQ,oCAAoC;KAErC,mCAAA,GAAsC;;;;;;;gCASd,GAAA,CAAI;;;;;;;;;;;;;;;;;;;;;;;UA2BvB,uCAAA;cACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenId4VciHolderServiceOptions.mjs","names":["openId4VciSupportedCredentialFormats: OpenId4VciSupportedCredentialFormats[]"],"sources":["../../src/openid4vc-holder/OpenId4VciHolderServiceOptions.ts"],"sourcesContent":["import type {\n AgentContext,\n Kms,\n MdocRecord,\n SdJwtVcRecord,\n W3cCredentialRecord,\n W3cV2CredentialRecord,\n} from '@credo-ts/core'\nimport type { CredentialOfferObject, IssuerMetadataResult } from '@openid4vc/openid4vci'\nimport { AuthorizationFlow as OpenId4VciAuthorizationFlow } from '@openid4vc/openid4vci'\nimport type {\n OpenId4VcCredentialHolderBinding,\n OpenId4VciAccessTokenResponse,\n OpenId4VciCredentialConfigurationSupportedWithFormats,\n OpenId4VciCredentialConfigurationsSupportedWithFormats,\n OpenId4VciMetadata,\n} from '../shared'\nimport { OpenId4VciCredentialFormatProfile } from '../shared/models/OpenId4VciCredentialFormatProfile'\n\nexport { OpenId4VciAuthorizationFlow }\n\nexport type OpenId4VciSupportedCredentialFormats =\n | OpenId4VciCredentialFormatProfile.JwtVcJson\n | OpenId4VciCredentialFormatProfile.JwtVcJsonLd\n | OpenId4VciCredentialFormatProfile.SdJwtVc\n | OpenId4VciCredentialFormatProfile.SdJwtDc\n | OpenId4VciCredentialFormatProfile.LdpVc\n | OpenId4VciCredentialFormatProfile.MsoMdoc\n\nexport const openId4VciSupportedCredentialFormats: OpenId4VciSupportedCredentialFormats[] = [\n OpenId4VciCredentialFormatProfile.JwtVcJson,\n OpenId4VciCredentialFormatProfile.JwtVcJsonLd,\n OpenId4VciCredentialFormatProfile.SdJwtVc,\n OpenId4VciCredentialFormatProfile.SdJwtDc,\n OpenId4VciCredentialFormatProfile.LdpVc,\n OpenId4VciCredentialFormatProfile.MsoMdoc,\n]\n\nexport interface OpenId4VciDpopRequestOptions {\n jwk: Kms.PublicJwk\n alg: Kms.KnownJwaSignatureAlgorithm\n nonce?: string\n}\n\n/**\n * 'credential_accepted' The Credential was successfully stored in the Wallet.\n * 'credential_deleted' when the unsuccessful Credential issuance was caused by a user action.\n * 'credential_failure' otherwise.\n */\nexport type OpenId4VciNotificationEvent = 'credential_accepted' | 'credential_failure' | 'credential_deleted'\n\nexport type OpenId4VciRequestTokenResponse = {\n accessToken: string\n refreshToken?: string\n cNonce?: string\n dpop?: OpenId4VciDpopRequestOptions\n authorizationServer?: string\n\n accessTokenResponse: OpenId4VciAccessTokenResponse\n}\n\nexport interface OpenId4VciCredentialResponse {\n credentialConfigurationId: string\n credentialConfiguration: OpenId4VciCredentialConfigurationSupportedWithFormats\n\n /**\n * The record containing the credentials returned in the OpenID4VCI credential response\n *\n * The credential is returned as a record, which can be provided to the\n * respective `store()` method of each credential-specific API.\n *\n * The record contains the credential instance (instances in case of batch issuance)\n * along with metadata such as the VCT Type Metadata (in case of SD-JWT)\n */\n record: SdJwtVcRecord | MdocRecord | W3cCredentialRecord | W3cV2CredentialRecord\n\n notificationId?: string\n}\n\nexport interface OpenId4VciDeferredCredentialResponse {\n credentialConfigurationId: string\n credentialConfiguration: OpenId4VciCredentialConfigurationSupportedWithFormats\n transactionId: string\n interval?: number\n notificationId?: string\n /**\n * Mapping from JWK thumbprint values to KMS key ids that were submitted in the credential request.\n * These should be used when retrieving the deferred credentials, to store the associated kms key id\n * for each received credential.\n */\n jwkThumbprintKmsKeyIdMapping?: Record<string, string>\n}\n\nexport interface OpenId4VciResolvedCredentialOffer {\n metadata: IssuerMetadataResult\n credentialOfferPayload: CredentialOfferObject\n\n /**\n * Offered credential configurations with known formats\n */\n offeredCredentialConfigurations: OpenId4VciCredentialConfigurationsSupportedWithFormats\n}\n\nexport type OpenId4VciResolvedAuthorizationRequest =\n | {\n openid4vpRequestUrl: string\n authorizationFlow: OpenId4VciAuthorizationFlow.PresentationDuringIssuance\n authSession: string\n\n /**\n * DPoP request options if DPoP was used for the authorization challenge request\n */\n dpop?: OpenId4VciDpopRequestOptions\n }\n | {\n authorizationRequestUrl: string\n authorizationFlow: OpenId4VciAuthorizationFlow.Oauth2Redirect\n codeVerifier?: string\n\n /**\n * DPoP request options if DPoP was used for the pushed authorization reuqest\n */\n dpop?: OpenId4VciDpopRequestOptions\n }\n\nexport interface OpenId4VciSendNotificationOptions {\n metadata: IssuerMetadataResult\n\n notificationId: string\n\n /**\n * The access token obtained through @see requestToken\n */\n accessToken: string\n\n /**\n * The notification event\n *\n * 'credential_accepted' The Credential was successfully stored in the Wallet.\n * 'credential_deleted' when the unsuccessful Credential issuance was caused by a user action.\n * 'credential_failure' otherwise.\n */\n notificationEvent: OpenId4VciNotificationEvent\n\n dpop?: OpenId4VciDpopRequestOptions\n}\n\nexport interface OpenId4VcAuthorizationCodeTokenRequestOptions {\n resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer\n code: string\n clientId: string\n codeVerifier?: string\n redirectUri?: string\n\n txCode?: never\n\n /**\n * DPoP parameters to use in the request if supported by the authorization server.\n *\n * If DPoP was already used in the initiateAuthorization method, it should be provided\n * here as well and be bound to the same key.\n */\n dpop?: OpenId4VciDpopRequestOptions\n\n /**\n * The wallet attestation to send to the issuer. This will only be used\n * if client attestations are supported by the issuer, and should be provided\n * if wallet attestation was provided in the authorization request as well.\n *\n * A Proof of Possession will be created based on the wallet attestation,\n * so the key bound to the wallet attestation must be in the wallet.\n */\n walletAttestationJwt?: string\n}\n\n// TODO: support wallet attestation for pre-auth flow\nexport interface OpenId4VciPreAuthorizedTokenRequestOptions {\n resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer\n txCode?: string\n\n code?: undefined\n\n /**\n * DPoP parameters to use in the request if supported by the authorization server.\n */\n dpop?: OpenId4VciDpopRequestOptions\n\n /**\n * The wallet attestation to send to the issuer. This will only be used\n * if client attestations are supported by the issuer.\n *\n * A Proof of Possession will be created based on the wallet attestation,\n * so the key bound to the wallet attestation must be in the wallet.\n */\n walletAttestationJwt?: string\n}\n\nexport type OpenId4VciTokenRequestOptions =\n | OpenId4VciPreAuthorizedTokenRequestOptions\n | OpenId4VcAuthorizationCodeTokenRequestOptions\n\nexport type OpenId4VciTokenRefreshOptions = {\n refreshToken: string\n\n /**\n * The issuer metadata.\n */\n issuerMetadata: IssuerMetadataResult\n\n /**\n * The authorization server where the refresh token was obtained from.\n */\n authorizationServer?: string\n\n /**\n * DPoP parameters to use in the request if supported by the authorization server.\n */\n dpop?: OpenId4VciDpopRequestOptions\n\n /**\n * The client id used for authorization. Only required if authorization_code flow was used.\n */\n clientId?: string\n\n /**\n * The wallet attestation to send to the issuer. This will only be used\n * if client attestations are supported by the issuer, and should be provided\n * if wallet attestation was provided in the authorization request as well.\n *\n * A Proof of Possession will be created based on the wallet attestation,\n * so the key bound to the wallet attestation must be in the wallet.\n */\n walletAttestationJwt?: string\n}\n\nexport interface OpenId4VciRetrieveAuthorizationCodeUsingPresentationOptions {\n resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer\n dpop?: OpenId4VciDpopRequestOptions\n\n /**\n * The wallet attestation to send to the issuer. This will only be used\n * if client attestations are supported by the issuer, and should be provided\n * if wallet attestation was provided in the authorization request as well.\n *\n * A Proof of Possession will be created based on the wallet attestation,\n * so the key bound to the wallet attestation must be in the wallet.\n */\n walletAttestationJwt?: string\n\n /**\n * auth session returned at an earlier call to the authorization challenge endpoint\n */\n authSession: string\n\n /**\n * Presentation during issuance session returned by the verifier after submitting a valid presentation\n */\n presentationDuringIssuanceSession?: string\n}\n\nexport interface OpenId4VciCredentialRequestOptions extends Omit<OpenId4VciAcceptCredentialOfferOptions, 'userPin'> {\n resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer\n accessToken: string\n cNonce?: string\n dpop?: OpenId4VciDpopRequestOptions\n\n /**\n * The client id used for authorization. Only required if authorization_code flow was used.\n */\n clientId?: string\n}\n\n/**\n * Options that are used to accept a credential offer for both the pre-authorized code flow and authorization code flow.\n * NOTE: Merge with @see OpenId4VciCredentialRequestOptions for 0.6\n */\nexport interface OpenId4VciAcceptCredentialOfferOptions {\n /**\n * This is the list of credentials configuration ids that will be requested from the issuer.\n * Should be a list of ids of the credentials that are included in the credential offer.\n * If not provided all offered credentials will be requested.\n */\n credentialConfigurationIds?: string[]\n\n verifyCredentialStatus?: boolean\n\n /**\n * A list of allowed proof of possession signature algorithms in order of preference.\n *\n * Note that the signature algorithms must be supported by the wallet implementation.\n * Signature algorithms that are not supported by the wallet will be ignored.\n *\n * The proof of possession (pop) signature algorithm is used in the credential request\n * to bind the credential to a did. In most cases the JWA signature algorithm\n * that is used in the pop will determine the cryptographic suite that is used\n * for signing the credential, but this not a requirement for the spec. E.g. if the\n * pop uses EdDsa, the credential will most commonly also use EdDsa, or Ed25519Signature2018/2020.\n */\n allowedProofOfPossessionSignatureAlgorithms?: Kms.KnownJwaSignatureAlgorithm[]\n\n /**\n * A function that should resolve key material for binding the to-be-issued credential\n * to the holder based on the options passed. This key material will be used for signing\n * the proof of possession included in the credential request.\n *\n * This method will be called once for each of the credentials that are included\n * in the credential offer.\n *\n * Based on the credential format, JWA signature algorithm, verification method types\n * and binding methods (did methods, jwk), the resolver must return an object\n * conformant to the `CredentialHolderBinding` interface, which will be used\n * for the proof of possession signature.\n */\n credentialBindingResolver: OpenId4VciCredentialBindingResolver\n}\n\n/**\n * Options to request deferred credentials from the issuer.\n */\nexport interface OpenId4VciDeferredCredentialRequestOptions {\n issuerMetadata: IssuerMetadataResult\n transactionId: string\n credentialConfigurationId: string\n credentialConfiguration: OpenId4VciCredentialConfigurationSupportedWithFormats\n verifyCredentialStatus?: boolean\n accessToken: string\n dpop?: OpenId4VciDpopRequestOptions\n\n /**\n * Mapping from JWK thumbprint values to KMS key ids that were submitted in the credential request.\n * These were returned in the deferred credential return value in case JWKs were used in the proof\n * of possession of the credential request\n */\n jwkThumbprintKmsKeyIdMapping?: Record<string, string>\n}\n\n/**\n * Options that are used for the authorization code flow.\n */\nexport interface OpenId4VciAuthCodeFlowOptions {\n clientId: string\n\n /**\n * The wallet attestation to send to the issuer. This will only be used\n * if client attestations and PAR are supported by the issuer.\n *\n * A Proof of Possesion will be created based on the wallet attestation,\n * so the key bound to the wallet attestation must be in the wallet.\n */\n walletAttestationJwt?: string\n\n redirectUri: string\n scope?: string[]\n}\n\nexport interface OpenId4VciCredentialBindingOptions {\n agentContext: AgentContext\n\n /**\n * The OpenID4VCI metadata, consisting of the draft version used,\n * the issuer metadatan and the authorization server metadata\n */\n metadata: OpenId4VciMetadata\n\n /**\n * The credential format that will be requested from the issuer.\n * E.g. `jwt_vc` or `ldp_vc`.\n */\n credentialFormat: OpenId4VciSupportedCredentialFormats\n\n /**\n * The max batch size as configured by the issuer. If the issuer has not indicated support for batch issuance\n * this will be `1`.\n */\n issuerMaxBatchSize: number\n\n /**\n * The proof types supported by the credential issuer that are also supported\n * by credo. Currently `jwt` and `attestation` are supported.\n *\n * Each proof type will list the supported algorithms, key types\n * and whether key attesations are required\n */\n proofTypes: OpenId4VciProofOfPressionProofTypes\n\n /**\n * The id of the credential configuration that will be requested from the issuer.\n */\n credentialConfigurationId: string\n\n /**\n * The credential configuration that will be requested from the issuer.\n */\n credentialConfiguration: OpenId4VciCredentialConfigurationSupportedWithFormats\n\n /**\n * Whether the issuer supports the `did` cryptographic binding method,\n * indicating they support all did methods. In most cases, they do not\n * support all did methods, and it means we have to make an assumption\n * about the did methods they support.\n *\n * If this value is `false`, the `supportedDidMethods` property will\n * contain a list of supported did methods.\n *\n * NOTE: when key attestations are required for a specific proof type, support for did method\n * binding is not supported at the moment, as there's no way to indicate which did the credential\n * should be bound to.\n * https://github.com/openid/OpenID4VCI/issues/475\n */\n supportsAllDidMethods: boolean\n\n /**\n * A list of supported did methods. This is only used if the `supportsAllDidMethods`\n * property is `false`. When this array is populated, the returned verification method\n * MUST be based on one of these did methods.\n *\n * The did methods are returned in the format `did:<method>`, e.g. `did:web`.\n *\n * The value is undefined in the case the supported did methods could not be extracted.\n * This is the case when the issuer didn't include the supported did methods in the issuer metadata.\n *\n * NOTE: an empty array (no did methods supported) has a different meaning from the value\n * being undefined (the supported did methods could not be extracted). If `supportsAllDidMethods`\n * is true, the value of this property MUST be ignored.\n *\n * NOTE: when key attestations are required for a specific proof type, support for did method\n * binding is not supported at the moment, as there's no way to indicate which did the credential\n * should be bound to.\n * https://github.com/openid/OpenID4VCI/issues/475\n */\n supportedDidMethods?: string[]\n\n /**\n * Whether the issuer supports the `jwk` cryptographic binding method,\n * indicating they support proof of possession signatures bound to a jwk.\n */\n supportsJwk: boolean\n\n /**\n * The cNonce that will be used for the credential request. May be used if dynamically creating a key attestation\n * that must include the cNonce.\n */\n cNonce: string\n}\n\n/**\n * The proof of possession verification method resolver is a function that can be passed by the\n * user of the framework and allows them to determine which verification method should be used\n * for the proof of possession signature.\n */\nexport type OpenId4VciCredentialBindingResolver = (\n options: OpenId4VciCredentialBindingOptions\n) => Promise<OpenId4VcCredentialHolderBinding> | OpenId4VcCredentialHolderBinding\n\nexport type OpenId4VciProofOfPressionProofTypes = Record<\n 'jwt' | 'attestation',\n | {\n /**\n * The JWA Signature Algorithm(s) that can be used in the proof of possession.\n * This is based on the `allowedProofOfPossessionSignatureAlgorithms` passed\n * to the request credential method, and the supported proof type signature\n * algorithms for the specific credential configuration\n */\n supportedSignatureAlgorithms: Kms.KnownJwaSignatureAlgorithm[]\n\n /**\n * Whether key attestations are required and which level needs to be met. If the object\n * is not defined, it can be interpreted that key attestations are not required.\n *\n * OpenID4VCI defined common levels in https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#appendix-D.2, such as:\n * - `iso_18045_high`\n * - `iso_18045_moderate`\n * - `iso_18045_enhanced-basic`\n * - `iso_18045_basic`\n *\n * Other values may be defined and present as well. When key attestations are required you MUST return a key attestation.\n * If `userAuthentication` or `keyStorage` are defined you MUST return a key attestation that reaches the level as required\n * by the `keyStorage` and `userAuthentication` values.\n */\n keyAttestationsRequired?: {\n keyStorage?: string[]\n userAuthentication?: string[]\n }\n }\n | undefined\n>\n\n/**\n * @internal\n */\nexport interface OpenId4VciProofOfPossessionRequirements {\n proofTypes: OpenId4VciProofOfPressionProofTypes\n supportedDidMethods?: string[]\n supportsAllDidMethods: boolean\n supportsJwk: boolean\n}\n"],"mappings":";;;;AA6BA,MAAaA,uCAA+E;CAC1F,kCAAkC;CAClC,kCAAkC;CAClC,kCAAkC;CAClC,kCAAkC;CAClC,kCAAkC;CAClC,kCAAkC;CACnC"}
|
|
1
|
+
{"version":3,"file":"OpenId4VciHolderServiceOptions.mjs","names":["openId4VciSupportedCredentialFormats: OpenId4VciSupportedCredentialFormats[]"],"sources":["../../src/openid4vc-holder/OpenId4VciHolderServiceOptions.ts"],"sourcesContent":["import type {\n AgentContext,\n Kms,\n MdocRecord,\n SdJwtVcRecord,\n W3cCredentialRecord,\n W3cV2CredentialRecord,\n} from '@credo-ts/core'\nimport type { CredentialOfferObject, IssuerMetadataResult } from '@openid4vc/openid4vci'\nimport { AuthorizationFlow as OpenId4VciAuthorizationFlow } from '@openid4vc/openid4vci'\nimport type {\n OpenId4VcCredentialHolderBinding,\n OpenId4VciAccessTokenResponse,\n OpenId4VciCredentialConfigurationSupportedWithFormats,\n OpenId4VciCredentialConfigurationsSupportedWithFormats,\n OpenId4VciMetadata,\n} from '../shared'\nimport { OpenId4VciCredentialFormatProfile } from '../shared/models/OpenId4VciCredentialFormatProfile'\n\nexport { OpenId4VciAuthorizationFlow }\n\nexport type OpenId4VciSupportedCredentialFormats =\n | OpenId4VciCredentialFormatProfile.JwtVcJson\n | OpenId4VciCredentialFormatProfile.JwtVcJsonLd\n | OpenId4VciCredentialFormatProfile.SdJwtVc\n | OpenId4VciCredentialFormatProfile.SdJwtDc\n | OpenId4VciCredentialFormatProfile.LdpVc\n | OpenId4VciCredentialFormatProfile.MsoMdoc\n\nexport const openId4VciSupportedCredentialFormats: OpenId4VciSupportedCredentialFormats[] = [\n OpenId4VciCredentialFormatProfile.JwtVcJson,\n OpenId4VciCredentialFormatProfile.JwtVcJsonLd,\n OpenId4VciCredentialFormatProfile.SdJwtVc,\n OpenId4VciCredentialFormatProfile.SdJwtDc,\n OpenId4VciCredentialFormatProfile.LdpVc,\n OpenId4VciCredentialFormatProfile.MsoMdoc,\n]\n\nexport interface OpenId4VciDpopRequestOptions {\n jwk: Kms.PublicJwk\n alg: Kms.KnownJwaSignatureAlgorithm\n nonce?: string\n}\n\n/**\n * 'credential_accepted' The Credential was successfully stored in the Wallet.\n * 'credential_deleted' when the unsuccessful Credential issuance was caused by a user action.\n * 'credential_failure' otherwise.\n */\nexport type OpenId4VciNotificationEvent = 'credential_accepted' | 'credential_failure' | 'credential_deleted'\n\nexport type OpenId4VciRequestTokenResponse = {\n accessToken: string\n refreshToken?: string\n cNonce?: string\n dpop?: OpenId4VciDpopRequestOptions\n authorizationServer?: string\n\n accessTokenResponse: OpenId4VciAccessTokenResponse\n}\n\nexport interface OpenId4VciCredentialResponse {\n credentialConfigurationId: string\n credentialConfiguration: OpenId4VciCredentialConfigurationSupportedWithFormats\n\n /**\n * The record containing the credentials returned in the OpenID4VCI credential response\n *\n * The credential is returned as a record, which can be provided to the\n * respective `store()` method of each credential-specific API.\n *\n * The record contains the credential instance (instances in case of batch issuance)\n * along with metadata such as the VCT Type Metadata (in case of SD-JWT)\n */\n record: SdJwtVcRecord | MdocRecord | W3cCredentialRecord | W3cV2CredentialRecord\n\n notificationId?: string\n}\n\nexport interface OpenId4VciDeferredCredentialResponse {\n credentialConfigurationId: string\n credentialConfiguration: OpenId4VciCredentialConfigurationSupportedWithFormats\n transactionId: string\n interval?: number\n notificationId?: string\n /**\n * Mapping from JWK thumbprint values to KMS key ids that were submitted in the credential request.\n * These should be used when retrieving the deferred credentials, to store the associated kms key id\n * for each received credential.\n */\n jwkThumbprintKmsKeyIdMapping?: Record<string, string>\n}\n\nexport interface OpenId4VciResolvedCredentialOffer {\n metadata: IssuerMetadataResult\n credentialOfferPayload: CredentialOfferObject\n\n /**\n * Offered credential configurations with known formats\n */\n offeredCredentialConfigurations: OpenId4VciCredentialConfigurationsSupportedWithFormats\n}\n\nexport type OpenId4VciResolvedAuthorizationRequest =\n | {\n openid4vpRequestUrl: string\n authorizationFlow: OpenId4VciAuthorizationFlow.PresentationDuringIssuance\n authSession: string\n\n /**\n * DPoP request options if DPoP was used for the authorization challenge request\n */\n dpop?: OpenId4VciDpopRequestOptions\n }\n | {\n authorizationRequestUrl: string\n authorizationFlow: OpenId4VciAuthorizationFlow.Oauth2Redirect\n codeVerifier?: string\n\n /**\n * DPoP request options if DPoP was used for the pushed authorization reuqest\n */\n dpop?: OpenId4VciDpopRequestOptions\n }\n\nexport interface OpenId4VciSendNotificationOptions {\n metadata: IssuerMetadataResult\n\n notificationId: string\n\n /**\n * The access token obtained through @see requestToken\n */\n accessToken: string\n\n /**\n * The notification event\n *\n * 'credential_accepted' The Credential was successfully stored in the Wallet.\n * 'credential_deleted' when the unsuccessful Credential issuance was caused by a user action.\n * 'credential_failure' otherwise.\n */\n notificationEvent: OpenId4VciNotificationEvent\n\n dpop?: OpenId4VciDpopRequestOptions\n}\n\nexport interface OpenId4VcParseAndVerifyAuthorizationResponseOptions {\n authorizationResponseRedirectUrl: string\n resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer\n}\n\nexport interface OpenId4VcAuthorizationCodeTokenRequestOptions {\n resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer\n code: string\n clientId: string\n codeVerifier?: string\n redirectUri?: string\n\n txCode?: never\n\n /**\n * DPoP parameters to use in the request if supported by the authorization server.\n *\n * If DPoP was already used in the initiateAuthorization method, it should be provided\n * here as well and be bound to the same key.\n */\n dpop?: OpenId4VciDpopRequestOptions\n\n /**\n * The wallet attestation to send to the issuer. This will only be used\n * if client attestations are supported by the issuer, and should be provided\n * if wallet attestation was provided in the authorization request as well.\n *\n * A Proof of Possession will be created based on the wallet attestation,\n * so the key bound to the wallet attestation must be in the wallet.\n */\n walletAttestationJwt?: string\n}\n\n// TODO: support wallet attestation for pre-auth flow\nexport interface OpenId4VciPreAuthorizedTokenRequestOptions {\n resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer\n txCode?: string\n\n code?: undefined\n\n /**\n * DPoP parameters to use in the request if supported by the authorization server.\n */\n dpop?: OpenId4VciDpopRequestOptions\n\n /**\n * The wallet attestation to send to the issuer. This will only be used\n * if client attestations are supported by the issuer.\n *\n * A Proof of Possession will be created based on the wallet attestation,\n * so the key bound to the wallet attestation must be in the wallet.\n */\n walletAttestationJwt?: string\n}\n\nexport type OpenId4VciTokenRequestOptions =\n | OpenId4VciPreAuthorizedTokenRequestOptions\n | OpenId4VcAuthorizationCodeTokenRequestOptions\n\nexport type OpenId4VciTokenRefreshOptions = {\n refreshToken: string\n\n /**\n * The issuer metadata.\n */\n issuerMetadata: IssuerMetadataResult\n\n /**\n * The authorization server where the refresh token was obtained from.\n */\n authorizationServer?: string\n\n /**\n * DPoP parameters to use in the request if supported by the authorization server.\n */\n dpop?: OpenId4VciDpopRequestOptions\n\n /**\n * The client id used for authorization. Only required if authorization_code flow was used.\n */\n clientId?: string\n\n /**\n * The wallet attestation to send to the issuer. This will only be used\n * if client attestations are supported by the issuer, and should be provided\n * if wallet attestation was provided in the authorization request as well.\n *\n * A Proof of Possession will be created based on the wallet attestation,\n * so the key bound to the wallet attestation must be in the wallet.\n */\n walletAttestationJwt?: string\n}\n\nexport interface OpenId4VciRetrieveAuthorizationCodeUsingPresentationOptions {\n resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer\n dpop?: OpenId4VciDpopRequestOptions\n\n /**\n * The wallet attestation to send to the issuer. This will only be used\n * if client attestations are supported by the issuer, and should be provided\n * if wallet attestation was provided in the authorization request as well.\n *\n * A Proof of Possession will be created based on the wallet attestation,\n * so the key bound to the wallet attestation must be in the wallet.\n */\n walletAttestationJwt?: string\n\n /**\n * auth session returned at an earlier call to the authorization challenge endpoint\n */\n authSession: string\n\n /**\n * Presentation during issuance session returned by the verifier after submitting a valid presentation\n */\n presentationDuringIssuanceSession?: string\n}\n\nexport interface OpenId4VciCredentialRequestOptions extends Omit<OpenId4VciAcceptCredentialOfferOptions, 'userPin'> {\n resolvedCredentialOffer: OpenId4VciResolvedCredentialOffer\n accessToken: string\n cNonce?: string\n dpop?: OpenId4VciDpopRequestOptions\n\n /**\n * The client id used for authorization. Only required if authorization_code flow was used.\n */\n clientId?: string\n}\n\n/**\n * Options that are used to accept a credential offer for both the pre-authorized code flow and authorization code flow.\n * NOTE: Merge with @see OpenId4VciCredentialRequestOptions for 0.6\n */\nexport interface OpenId4VciAcceptCredentialOfferOptions {\n /**\n * This is the list of credentials configuration ids that will be requested from the issuer.\n * Should be a list of ids of the credentials that are included in the credential offer.\n * If not provided all offered credentials will be requested.\n */\n credentialConfigurationIds?: string[]\n\n verifyCredentialStatus?: boolean\n\n /**\n * A list of allowed proof of possession signature algorithms in order of preference.\n *\n * Note that the signature algorithms must be supported by the wallet implementation.\n * Signature algorithms that are not supported by the wallet will be ignored.\n *\n * The proof of possession (pop) signature algorithm is used in the credential request\n * to bind the credential to a did. In most cases the JWA signature algorithm\n * that is used in the pop will determine the cryptographic suite that is used\n * for signing the credential, but this not a requirement for the spec. E.g. if the\n * pop uses EdDsa, the credential will most commonly also use EdDsa, or Ed25519Signature2018/2020.\n */\n allowedProofOfPossessionSignatureAlgorithms?: Kms.KnownJwaSignatureAlgorithm[]\n\n /**\n * A function that should resolve key material for binding the to-be-issued credential\n * to the holder based on the options passed. This key material will be used for signing\n * the proof of possession included in the credential request.\n *\n * This method will be called once for each of the credentials that are included\n * in the credential offer.\n *\n * Based on the credential format, JWA signature algorithm, verification method types\n * and binding methods (did methods, jwk), the resolver must return an object\n * conformant to the `CredentialHolderBinding` interface, which will be used\n * for the proof of possession signature.\n */\n credentialBindingResolver: OpenId4VciCredentialBindingResolver\n}\n\n/**\n * Options to request deferred credentials from the issuer.\n */\nexport interface OpenId4VciDeferredCredentialRequestOptions {\n issuerMetadata: IssuerMetadataResult\n transactionId: string\n credentialConfigurationId: string\n credentialConfiguration: OpenId4VciCredentialConfigurationSupportedWithFormats\n verifyCredentialStatus?: boolean\n accessToken: string\n dpop?: OpenId4VciDpopRequestOptions\n\n /**\n * Mapping from JWK thumbprint values to KMS key ids that were submitted in the credential request.\n * These were returned in the deferred credential return value in case JWKs were used in the proof\n * of possession of the credential request\n */\n jwkThumbprintKmsKeyIdMapping?: Record<string, string>\n}\n\n/**\n * Options that are used for the authorization code flow.\n */\nexport interface OpenId4VciAuthCodeFlowOptions {\n clientId: string\n\n /**\n * The wallet attestation to send to the issuer. This will only be used\n * if client attestations and PAR are supported by the issuer.\n *\n * A Proof of Possesion will be created based on the wallet attestation,\n * so the key bound to the wallet attestation must be in the wallet.\n */\n walletAttestationJwt?: string\n\n redirectUri: string\n scope?: string[]\n}\n\nexport interface OpenId4VciCredentialBindingOptions {\n agentContext: AgentContext\n\n /**\n * The OpenID4VCI metadata, consisting of the draft version used,\n * the issuer metadatan and the authorization server metadata\n */\n metadata: OpenId4VciMetadata\n\n /**\n * The credential format that will be requested from the issuer.\n * E.g. `jwt_vc` or `ldp_vc`.\n */\n credentialFormat: OpenId4VciSupportedCredentialFormats\n\n /**\n * The max batch size as configured by the issuer. If the issuer has not indicated support for batch issuance\n * this will be `1`.\n */\n issuerMaxBatchSize: number\n\n /**\n * The proof types supported by the credential issuer that are also supported\n * by credo. Currently `jwt` and `attestation` are supported.\n *\n * Each proof type will list the supported algorithms, key types\n * and whether key attesations are required\n */\n proofTypes: OpenId4VciProofOfPressionProofTypes\n\n /**\n * The id of the credential configuration that will be requested from the issuer.\n */\n credentialConfigurationId: string\n\n /**\n * The credential configuration that will be requested from the issuer.\n */\n credentialConfiguration: OpenId4VciCredentialConfigurationSupportedWithFormats\n\n /**\n * Whether the issuer supports the `did` cryptographic binding method,\n * indicating they support all did methods. In most cases, they do not\n * support all did methods, and it means we have to make an assumption\n * about the did methods they support.\n *\n * If this value is `false`, the `supportedDidMethods` property will\n * contain a list of supported did methods.\n *\n * NOTE: when key attestations are required for a specific proof type, support for did method\n * binding is not supported at the moment, as there's no way to indicate which did the credential\n * should be bound to.\n * https://github.com/openid/OpenID4VCI/issues/475\n */\n supportsAllDidMethods: boolean\n\n /**\n * A list of supported did methods. This is only used if the `supportsAllDidMethods`\n * property is `false`. When this array is populated, the returned verification method\n * MUST be based on one of these did methods.\n *\n * The did methods are returned in the format `did:<method>`, e.g. `did:web`.\n *\n * The value is undefined in the case the supported did methods could not be extracted.\n * This is the case when the issuer didn't include the supported did methods in the issuer metadata.\n *\n * NOTE: an empty array (no did methods supported) has a different meaning from the value\n * being undefined (the supported did methods could not be extracted). If `supportsAllDidMethods`\n * is true, the value of this property MUST be ignored.\n *\n * NOTE: when key attestations are required for a specific proof type, support for did method\n * binding is not supported at the moment, as there's no way to indicate which did the credential\n * should be bound to.\n * https://github.com/openid/OpenID4VCI/issues/475\n */\n supportedDidMethods?: string[]\n\n /**\n * Whether the issuer supports the `jwk` cryptographic binding method,\n * indicating they support proof of possession signatures bound to a jwk.\n */\n supportsJwk: boolean\n\n /**\n * The cNonce that will be used for the credential request. May be used if dynamically creating a key attestation\n * that must include the cNonce.\n */\n cNonce: string\n}\n\n/**\n * The proof of possession verification method resolver is a function that can be passed by the\n * user of the framework and allows them to determine which verification method should be used\n * for the proof of possession signature.\n */\nexport type OpenId4VciCredentialBindingResolver = (\n options: OpenId4VciCredentialBindingOptions\n) => Promise<OpenId4VcCredentialHolderBinding> | OpenId4VcCredentialHolderBinding\n\nexport type OpenId4VciProofOfPressionProofTypes = Record<\n 'jwt' | 'attestation',\n | {\n /**\n * The JWA Signature Algorithm(s) that can be used in the proof of possession.\n * This is based on the `allowedProofOfPossessionSignatureAlgorithms` passed\n * to the request credential method, and the supported proof type signature\n * algorithms for the specific credential configuration\n */\n supportedSignatureAlgorithms: Kms.KnownJwaSignatureAlgorithm[]\n\n /**\n * Whether key attestations are required and which level needs to be met. If the object\n * is not defined, it can be interpreted that key attestations are not required.\n *\n * OpenID4VCI defined common levels in https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#appendix-D.2, such as:\n * - `iso_18045_high`\n * - `iso_18045_moderate`\n * - `iso_18045_enhanced-basic`\n * - `iso_18045_basic`\n *\n * Other values may be defined and present as well. When key attestations are required you MUST return a key attestation.\n * If `userAuthentication` or `keyStorage` are defined you MUST return a key attestation that reaches the level as required\n * by the `keyStorage` and `userAuthentication` values.\n */\n keyAttestationsRequired?: {\n keyStorage?: string[]\n userAuthentication?: string[]\n }\n }\n | undefined\n>\n\n/**\n * @internal\n */\nexport interface OpenId4VciProofOfPossessionRequirements {\n proofTypes: OpenId4VciProofOfPressionProofTypes\n supportedDidMethods?: string[]\n supportsAllDidMethods: boolean\n supportsJwk: boolean\n}\n"],"mappings":";;;;AA6BA,MAAaA,uCAA+E;CAC1F,kCAAkC;CAClC,kCAAkC;CAClC,kCAAkC;CAClC,kCAAkC;CAClC,kCAAkC;CAClC,kCAAkC;CACnC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OpenId4VpAcceptAuthorizationRequestOptions, OpenId4VpResolvedAuthorizationRequest, ParsedTransactionDataEntry, ResolveOpenId4VpAuthorizationRequestOptions } from "./OpenId4vpHolderServiceOptions.mjs";
|
|
2
|
-
import { OpenId4VcAuthorizationCodeTokenRequestOptions, OpenId4VciAcceptCredentialOfferOptions, OpenId4VciAuthCodeFlowOptions, OpenId4VciAuthorizationFlow, OpenId4VciCredentialBindingOptions, OpenId4VciCredentialBindingResolver, OpenId4VciCredentialRequestOptions, OpenId4VciCredentialResponse, OpenId4VciDeferredCredentialRequestOptions, OpenId4VciDeferredCredentialResponse, OpenId4VciDpopRequestOptions, OpenId4VciNotificationEvent, OpenId4VciPreAuthorizedTokenRequestOptions, OpenId4VciProofOfPossessionRequirements, OpenId4VciProofOfPressionProofTypes, OpenId4VciRequestTokenResponse, OpenId4VciResolvedAuthorizationRequest, OpenId4VciResolvedCredentialOffer, OpenId4VciRetrieveAuthorizationCodeUsingPresentationOptions, OpenId4VciSendNotificationOptions, OpenId4VciSupportedCredentialFormats, OpenId4VciTokenRefreshOptions, OpenId4VciTokenRequestOptions, openId4VciSupportedCredentialFormats } from "./OpenId4VciHolderServiceOptions.mjs";
|
|
2
|
+
import { OpenId4VcAuthorizationCodeTokenRequestOptions, OpenId4VcParseAndVerifyAuthorizationResponseOptions, OpenId4VciAcceptCredentialOfferOptions, OpenId4VciAuthCodeFlowOptions, OpenId4VciAuthorizationFlow, OpenId4VciCredentialBindingOptions, OpenId4VciCredentialBindingResolver, OpenId4VciCredentialRequestOptions, OpenId4VciCredentialResponse, OpenId4VciDeferredCredentialRequestOptions, OpenId4VciDeferredCredentialResponse, OpenId4VciDpopRequestOptions, OpenId4VciNotificationEvent, OpenId4VciPreAuthorizedTokenRequestOptions, OpenId4VciProofOfPossessionRequirements, OpenId4VciProofOfPressionProofTypes, OpenId4VciRequestTokenResponse, OpenId4VciResolvedAuthorizationRequest, OpenId4VciResolvedCredentialOffer, OpenId4VciRetrieveAuthorizationCodeUsingPresentationOptions, OpenId4VciSendNotificationOptions, OpenId4VciSupportedCredentialFormats, OpenId4VciTokenRefreshOptions, OpenId4VciTokenRequestOptions, openId4VciSupportedCredentialFormats } from "./OpenId4VciHolderServiceOptions.mjs";
|
|
3
3
|
import { OpenId4VciHolderService } from "./OpenId4VciHolderService.mjs";
|
|
4
4
|
import { OpenId4VpHolderService } from "./OpenId4vpHolderService.mjs";
|
|
5
5
|
import { OpenId4VcHolderApi } from "./OpenId4VcHolderApi.mjs";
|
|
@@ -114,6 +114,7 @@ declare class OpenId4VcIssuerApi {
|
|
|
114
114
|
authorization_challenge_endpoint?: string | undefined;
|
|
115
115
|
'pre-authorized_grant_anonymous_access_supported'?: boolean | undefined;
|
|
116
116
|
client_attestation_pop_nonce_required?: boolean | undefined;
|
|
117
|
+
authorization_response_iss_parameter_supported?: boolean | undefined;
|
|
117
118
|
} | {
|
|
118
119
|
issuer: string;
|
|
119
120
|
token_endpoint: string;
|
|
@@ -126,6 +127,7 @@ declare class OpenId4VcIssuerApi {
|
|
|
126
127
|
require_pushed_authorization_requests: true;
|
|
127
128
|
code_challenge_methods_supported: _openid4vc_oauth20.PkceCodeChallengeMethod[];
|
|
128
129
|
dpop_signing_alg_values_supported: ["HS256" | "HS384" | "HS512" | "RS256" | "RS384" | "RS512" | "ES256" | "ES384" | "ES512" | "PS256" | "PS384" | "PS512" | "EdDSA" | "Ed25519" | "ES256K", ...("HS256" | "HS384" | "HS512" | "RS256" | "RS384" | "RS512" | "ES256" | "ES384" | "ES512" | "PS256" | "PS384" | "PS512" | "EdDSA" | "Ed25519" | "ES256K")[]] | undefined;
|
|
130
|
+
authorization_response_iss_parameter_supported: true;
|
|
129
131
|
})[];
|
|
130
132
|
knownCredentialConfigurations: OpenId4VciCredentialConfigurationsSupportedWithFormats;
|
|
131
133
|
signedMetadataJwt: string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenId4VcIssuerApi.d.mts","names":[],"sources":["../../src/openid4vc-issuer/OpenId4VcIssuerApi.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;cAmBa,kBAAA;mBAEe;;EAFf,QAAA,sBAAkB;EAEH,WAAA,CAAA,MAAA,EAAA,2BAAA,EAAA,YAAA,EACF,YADE,EAAA,sBAAA,EAEQ,sBAFR;EAAA,aAAA,CAAA,CAAA,EAKA,OALA,CAE8B,qBAAA,EAF9B,CAAA;EACF,mBAAA,CAAA,QAAA,EAAA,MAAA,CAAA,EAQyB,OARzB,CAIE,qBAAA,CAJF;EACU;;;;EAOe,YAAA,CAAA,OAAA,EAQd,6BARc,CAAA,EAQe,OARf,CAQe,qBAAA,CARf;EAQd;;;EAOsB,2BAAA,CAAA,QAAA,EAAA,MAAA,CAAA,EAAA,OAAA,CAAA,IAAA,CAAA;EAKd,oBAAA,CAAA,OAAA,EAAA,kCAAA,CAAA,EAAkC,OAAlC,CAAA,IAAA,CAAA;EAAkC;;;;EAsCjC,8BAAA,CAAA,OAAA,EAZjC,+CAYiC,GAAA;IAAsC,QAAA,EAAA,MAAA;EAAuB,CAAA,CAAA,EAZxB,OAYwB,CAAA;IAU9F,eAAA,EAAA,MAAA;IAAyC,qBAAA,EAtBM,gCAsBN;;EAAgC;;;;;EAeQ,qBAAA,CAAA,OAAA,EAzBhD,sCAyBgD,GAAA;;MAzBa;qBAAvB;IAuCnC,eAAA,EAAA,MAAA;EAAA,CAAA,CAAA;EAKc;;;oCAlClD;;MAAyE;qBAAhC;;;;;;4CAezC;;MAAiF;qBAAhC;;;uCAcb;0BAd6C,sBAAA,CAAA
|
|
1
|
+
{"version":3,"file":"OpenId4VcIssuerApi.d.mts","names":[],"sources":["../../src/openid4vc-issuer/OpenId4VcIssuerApi.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;cAmBa,kBAAA;mBAEe;;EAFf,QAAA,sBAAkB;EAEH,WAAA,CAAA,MAAA,EAAA,2BAAA,EAAA,YAAA,EACF,YADE,EAAA,sBAAA,EAEQ,sBAFR;EAAA,aAAA,CAAA,CAAA,EAKA,OALA,CAE8B,qBAAA,EAF9B,CAAA;EACF,mBAAA,CAAA,QAAA,EAAA,MAAA,CAAA,EAQyB,OARzB,CAIE,qBAAA,CAJF;EACU;;;;EAOe,YAAA,CAAA,OAAA,EAQd,6BARc,CAAA,EAQe,OARf,CAQe,qBAAA,CARf;EAQd;;;EAOsB,2BAAA,CAAA,QAAA,EAAA,MAAA,CAAA,EAAA,OAAA,CAAA,IAAA,CAAA;EAKd,oBAAA,CAAA,OAAA,EAAA,kCAAA,CAAA,EAAkC,OAAlC,CAAA,IAAA,CAAA;EAAkC;;;;EAsCjC,8BAAA,CAAA,OAAA,EAZjC,+CAYiC,GAAA;IAAsC,QAAA,EAAA,MAAA;EAAuB,CAAA,CAAA,EAZxB,OAYwB,CAAA;IAU9F,eAAA,EAAA,MAAA;IAAyC,qBAAA,EAtBM,gCAsBN;;EAAgC;;;;;EAeQ,qBAAA,CAAA,OAAA,EAzBhD,sCAyBgD,GAAA;;MAzBa;qBAAvB;IAuCnC,eAAA,EAAA,MAAA;EAAA,CAAA,CAAA;EAKc;;;oCAlClD;;MAAyE;qBAAhC;;;;;;4CAezC;;MAAiF;qBAAhC;;;uCAcb;0BAd6C,sBAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qDAmB/B,QALd,8BAAA"}
|
|
@@ -11,8 +11,7 @@ import { OpenId4VcIssuerModuleConfig } from "./OpenId4VcIssuerModuleConfig.mjs";
|
|
|
11
11
|
import "../index.mjs";
|
|
12
12
|
import { AgentContext, Jwt, Query, QueryOptions, W3cCredentialService, W3cV2CredentialService } from "@credo-ts/core";
|
|
13
13
|
import { Jwk, Oauth2AuthorizationServer, Oauth2Client, Oauth2ResourceServer, PkceCodeChallengeMethod } from "@openid4vc/oauth2";
|
|
14
|
-
import
|
|
15
|
-
import { CredentialResponse, DeferredCredentialResponse, Openid4vciIssuer } from "@openid4vc/openid4vci";
|
|
14
|
+
import { CredentialResponse, DeferredCredentialResponse, Openid4vciIssuer, Openid4vciVersion } from "@openid4vc/openid4vci";
|
|
16
15
|
|
|
17
16
|
//#region src/openid4vc-issuer/OpenId4VcIssuerService.d.ts
|
|
18
17
|
/**
|
|
@@ -63,7 +62,7 @@ declare class OpenId4VcIssuerService {
|
|
|
63
62
|
* @param fetchExternalAuthorizationServerMetadata defaults to false
|
|
64
63
|
*/
|
|
65
64
|
getIssuerMetadata(agentContext: AgentContext, issuerRecord: OpenId4VcIssuerRecord, fetchExternalAuthorizationServerMetadata?: boolean): Promise<{
|
|
66
|
-
originalDraftVersion:
|
|
65
|
+
originalDraftVersion: Openid4vciVersion;
|
|
67
66
|
credentialIssuer: {
|
|
68
67
|
credential_issuer: string;
|
|
69
68
|
credential_endpoint: string;
|
|
@@ -103,6 +102,7 @@ declare class OpenId4VcIssuerService {
|
|
|
103
102
|
authorization_challenge_endpoint?: string | undefined;
|
|
104
103
|
'pre-authorized_grant_anonymous_access_supported'?: boolean | undefined;
|
|
105
104
|
client_attestation_pop_nonce_required?: boolean | undefined;
|
|
105
|
+
authorization_response_iss_parameter_supported?: boolean | undefined;
|
|
106
106
|
} | {
|
|
107
107
|
issuer: string;
|
|
108
108
|
token_endpoint: string;
|
|
@@ -115,6 +115,7 @@ declare class OpenId4VcIssuerService {
|
|
|
115
115
|
require_pushed_authorization_requests: true;
|
|
116
116
|
code_challenge_methods_supported: PkceCodeChallengeMethod[];
|
|
117
117
|
dpop_signing_alg_values_supported: ["HS256" | "HS384" | "HS512" | "RS256" | "RS384" | "RS512" | "ES256" | "ES384" | "ES512" | "PS256" | "PS384" | "PS512" | "EdDSA" | "Ed25519" | "ES256K", ...("HS256" | "HS384" | "HS512" | "RS256" | "RS384" | "RS512" | "ES256" | "ES384" | "ES512" | "PS256" | "PS384" | "PS512" | "EdDSA" | "Ed25519" | "ES256K")[]] | undefined;
|
|
118
|
+
authorization_response_iss_parameter_supported: true;
|
|
118
119
|
})[];
|
|
119
120
|
knownCredentialConfigurations: OpenId4VciCredentialConfigurationsSupportedWithFormats;
|
|
120
121
|
signedMetadataJwt: string | undefined;
|