@credo-ts/openid4vc 0.6.2-alpha-20251211115250 → 0.6.2-alpha-20251211125338
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/openid4vc-holder/OpenId4VciHolderService.mjs +16 -7
- package/build/openid4vc-holder/OpenId4VciHolderService.mjs.map +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerApi.d.mts +1 -1
- package/build/openid4vc-issuer/OpenId4VcIssuerService.d.mts +3 -2
- package/build/openid4vc-issuer/OpenId4VcIssuerService.d.mts.map +1 -1
- package/package.json +7 -7
|
@@ -586,10 +586,19 @@ let OpenId4VciHolderService = class OpenId4VciHolderService$1 {
|
|
|
586
586
|
if (!credentials.every((c) => typeof c === "string")) throw new CredoError(`Received credential(s) of format ${format}, but not all credential(s) are a string. ${JSON.stringify(credentials)}`);
|
|
587
587
|
if (format === OpenId4VciCredentialFormatProfile.SdJwtDc || credentialConfiguration.vct) {
|
|
588
588
|
const sdJwtVcApi = agentContext.dependencyManager.resolve(SdJwtVcApi);
|
|
589
|
-
const verificationResults = await Promise.all(credentials.map((compactSdJwtVc, index) =>
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
589
|
+
const verificationResults = await Promise.all(credentials.map(async (compactSdJwtVc, index) => {
|
|
590
|
+
const result$1 = await sdJwtVcApi.verify({
|
|
591
|
+
compactSdJwtVc,
|
|
592
|
+
fetchTypeMetadata: index === 0
|
|
593
|
+
});
|
|
594
|
+
if (result$1.sdJwtVc?.holder?.method === "jwk") {
|
|
595
|
+
const jwkThumbprint = TypedArrayEncoder.toBase64(result$1.sdJwtVc.holder.jwk.getJwkThumbprint());
|
|
596
|
+
const kmsKeyId = options.jwkThumbprintKmsKeyIdMapping?.[jwkThumbprint];
|
|
597
|
+
if (!kmsKeyId) throw new CredoError(`Missing kmsKeyId for jwk with thumbprint ${jwkThumbprint}. A credential was issued for a key that was not in the credential request.`);
|
|
598
|
+
result$1.sdJwtVc.kmsKeyId = kmsKeyId;
|
|
599
|
+
}
|
|
600
|
+
return result$1;
|
|
601
|
+
}));
|
|
593
602
|
if (!verificationResults.every((result$1) => result$1.isValid)) {
|
|
594
603
|
agentContext.config.logger.error("Failed to validate credential(s)", { verificationResults });
|
|
595
604
|
throw new CredoError(`Failed to validate sd-jwt-vc credentials. Results = ${JSON.stringify(verificationResults, replaceError)}`);
|
|
@@ -687,10 +696,10 @@ let OpenId4VciHolderService = class OpenId4VciHolderService$1 {
|
|
|
687
696
|
const jwkThumbprint = TypedArrayEncoder.toBase64(mdoc.deviceKey.getJwkThumbprint());
|
|
688
697
|
const kmsKeyId = options.jwkThumbprintKmsKeyIdMapping?.[jwkThumbprint];
|
|
689
698
|
if (!kmsKeyId) throw new CredoError(`Missing kmsKeyId for jwk with thumbprint ${jwkThumbprint}. A credential was issued for a key that was not in the credential request.`);
|
|
699
|
+
mdoc.deviceKeyId = kmsKeyId;
|
|
690
700
|
return {
|
|
691
701
|
result: result$1,
|
|
692
|
-
mdoc
|
|
693
|
-
kmsKeyId
|
|
702
|
+
mdoc
|
|
694
703
|
};
|
|
695
704
|
}));
|
|
696
705
|
if (!result.every((r) => r.result.isValid)) {
|
|
@@ -700,7 +709,7 @@ let OpenId4VciHolderService = class OpenId4VciHolderService$1 {
|
|
|
700
709
|
return {
|
|
701
710
|
record: new MdocRecord({ credentialInstances: result.map((c) => ({
|
|
702
711
|
issuerSignedBase64Url: c.mdoc.base64Url,
|
|
703
|
-
kmsKeyId: c.
|
|
712
|
+
kmsKeyId: c.mdoc.deviceKeyId
|
|
704
713
|
})) }),
|
|
705
714
|
notificationId,
|
|
706
715
|
credentialConfigurationId,
|
|
@@ -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((compactSdJwtVc, index) =>\n sdJwtVcApi.verify({\n compactSdJwtVc,\n // Only load and verify it for the first instance\n fetchTypeMetadata: index === 0,\n })\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 return {\n result,\n mdoc,\n kmsKeyId,\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.kmsKeyId,\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 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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"}
|
|
@@ -74,7 +74,7 @@ declare class OpenId4VcIssuerApi {
|
|
|
74
74
|
deferredCredentialResponse: _openid4vc_openid4vci0.DeferredCredentialResponse;
|
|
75
75
|
}>;
|
|
76
76
|
getIssuerMetadata(issuerId: string): Promise<{
|
|
77
|
-
originalDraftVersion: _openid4vc_openid4vci0.
|
|
77
|
+
originalDraftVersion: _openid4vc_openid4vci0.Openid4vciVersion;
|
|
78
78
|
credentialIssuer: {
|
|
79
79
|
credential_issuer: string;
|
|
80
80
|
credential_endpoint: string;
|
|
@@ -11,7 +11,8 @@ 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
|
|
14
|
+
import * as _openid4vc_openid4vci2 from "@openid4vc/openid4vci";
|
|
15
|
+
import { CredentialResponse, DeferredCredentialResponse, Openid4vciIssuer } from "@openid4vc/openid4vci";
|
|
15
16
|
|
|
16
17
|
//#region src/openid4vc-issuer/OpenId4VcIssuerService.d.ts
|
|
17
18
|
/**
|
|
@@ -62,7 +63,7 @@ declare class OpenId4VcIssuerService {
|
|
|
62
63
|
* @param fetchExternalAuthorizationServerMetadata defaults to false
|
|
63
64
|
*/
|
|
64
65
|
getIssuerMetadata(agentContext: AgentContext, issuerRecord: OpenId4VcIssuerRecord, fetchExternalAuthorizationServerMetadata?: boolean): Promise<{
|
|
65
|
-
originalDraftVersion:
|
|
66
|
+
originalDraftVersion: _openid4vc_openid4vci2.Openid4vciVersion;
|
|
66
67
|
credentialIssuer: {
|
|
67
68
|
credential_issuer: string;
|
|
68
69
|
credential_endpoint: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenId4VcIssuerService.d.mts","names":[],"sources":["../../src/openid4vc-issuer/OpenId4VcIssuerService.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"OpenId4VcIssuerService.d.mts","names":[],"sources":["../../src/openid4vc-issuer/OpenId4VcIssuerService.ts"],"sourcesContent":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
".": "./build/index.mjs",
|
|
5
5
|
"./package.json": "./package.json"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.6.2-alpha-
|
|
7
|
+
"version": "0.6.2-alpha-20251211125338",
|
|
8
8
|
"files": [
|
|
9
9
|
"build"
|
|
10
10
|
],
|
|
@@ -30,18 +30,18 @@
|
|
|
30
30
|
"class-transformer": "0.5.1",
|
|
31
31
|
"rxjs": "^7.8.2",
|
|
32
32
|
"zod": "^4.1.12",
|
|
33
|
-
"@openid4vc/openid4vci": "^0.4.
|
|
34
|
-
"@openid4vc/oauth2": "^0.4.
|
|
35
|
-
"@openid4vc/openid4vp": "^0.4.
|
|
36
|
-
"@openid4vc/utils": "^0.4.
|
|
33
|
+
"@openid4vc/openid4vci": "^0.4.3",
|
|
34
|
+
"@openid4vc/oauth2": "^0.4.3",
|
|
35
|
+
"@openid4vc/openid4vp": "^0.4.3",
|
|
36
|
+
"@openid4vc/utils": "^0.4.3",
|
|
37
37
|
"@types/express": "^5.0.6",
|
|
38
38
|
"express": "^5.2.0",
|
|
39
|
-
"@credo-ts/core": "0.6.2-alpha-
|
|
39
|
+
"@credo-ts/core": "0.6.2-alpha-20251211125338"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"nock": "^14.0.10",
|
|
43
43
|
"typescript": "~5.9.3",
|
|
44
|
-
"@credo-ts/tenants": "0.6.2-alpha-
|
|
44
|
+
"@credo-ts/tenants": "0.6.2-alpha-20251211125338"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "tsdown --config-loader unconfig"
|