diff --git a/packages/consumption/src/modules/openid4vc/OpenId4VcController.ts b/packages/consumption/src/modules/openid4vc/OpenId4VcController.ts index 3ed6bd2a0..5049ba53e 100644 --- a/packages/consumption/src/modules/openid4vc/OpenId4VcController.ts +++ b/packages/consumption/src/modules/openid4vc/OpenId4VcController.ts @@ -1,3 +1,5 @@ +import { ClaimFormat } from "@credo-ts/core"; +import { OpenId4VpResolvedAuthorizationRequest } from "@credo-ts/openid4vc"; import { VerifiableCredential } from "@nmshd/content"; import { ConsumptionBaseController } from "../../consumption/ConsumptionBaseController"; import { ConsumptionController } from "../../consumption/ConsumptionController"; @@ -58,41 +60,56 @@ export class OpenId4VcController extends ConsumptionBaseController { }; } - public async fetchProofRequest(proofRequestUrl: string): Promise<{ data: string }> { + public async resolveAuthorizationRequest( + requestUrl: string + ): Promise<{ authorizationRequest: OpenId4VpResolvedAuthorizationRequest; usedCredentials: { id: string; data: string; type: string; displayInformation?: string }[] }> { const holder = new Holder(this.parent.accountController, this.parent.attributes); await holder.initializeAgent("96213c3d7fc8d4d6754c7a0fd969598e"); - const res = await holder.resolveProofRequest(proofRequestUrl); + const authorizationRequest = await holder.resolveAuthorizationRequest(requestUrl); + + // TODO: extract DTOs + + const matchedCredentialsSdJwtVc = authorizationRequest.presentationExchange?.credentialsForRequest.requirements + .map((entry) => + entry.submissionEntry + .map((subEntry) => subEntry.verifiableCredentials.filter((vc) => vc.claimFormat === ClaimFormat.SdJwtDc).map((vc) => vc.credentialRecord.compactSdJwtVc)) + .flat() + ) + .flat(); + + const allCredentials = await this.getVerifiableCredentials(); + + const usedCredentials = allCredentials.filter((credential) => matchedCredentialsSdJwtVc?.includes(credential.data)); + return { - data: JSON.stringify(res) + authorizationRequest, + usedCredentials }; } - public async acceptProofRequest(jsonEncodedRequest: string): Promise<{ status: number; message: string | Record | null }> { + public async acceptAuthorizationRequest( + authorizationRequest: OpenId4VpResolvedAuthorizationRequest + ): Promise<{ status: number; message: string | Record | null }> { const holder = new Holder(this.parent.accountController, this.parent.attributes); await holder.initializeAgent("96213c3d7fc8d4d6754c7a0fd969598e"); - const fetchedRequest = JSON.parse(jsonEncodedRequest); // parse the credential type to be sdjwt - const serverResponse = await holder.acceptPresentationRequest(fetchedRequest); + const serverResponse = await holder.acceptAuthorizationRequest(authorizationRequest); if (!serverResponse) throw new Error("No response from server"); return { status: serverResponse.status, message: serverResponse.body }; } - public async getVerifiableCredentials(ids: string[] | undefined): Promise { + public async getVerifiableCredentials(ids?: string[]): Promise<{ id: string; data: string; type: string; displayInformation?: string }[]> { const holder = new Holder(this.parent.accountController, this.parent.attributes); await holder.initializeAgent("96213c3d7fc8d4d6754c7a0fd969598e"); const credentials = await holder.getVerifiableCredentials(ids); - const result = []; - for (const credential of credentials) { - result.push({ - id: credential.id.toString(), - data: credential.content.value.value.toString(), - displayInformation: credential.content.value.displayInformation ?? undefined, - type: credential.content.value.type ?? undefined - }); - } - return result; + + return credentials.map((credential) => { + const value = credential.content.value as VerifiableCredential; + + return { id: credential.id.toString(), data: value.value, type: value.type, displayInformation: value.displayInformation }; + }); } } diff --git a/packages/consumption/src/modules/openid4vc/local/EnmeshedStorageService.ts b/packages/consumption/src/modules/openid4vc/local/EnmeshedStorageService.ts index 80af38f70..a47a8f63e 100644 --- a/packages/consumption/src/modules/openid4vc/local/EnmeshedStorageService.ts +++ b/packages/consumption/src/modules/openid4vc/local/EnmeshedStorageService.ts @@ -184,10 +184,10 @@ export class EnmeshedStorageService implements StorageServ } // should only be used for exporting data out of the credo environment - public async getAllAsAttributes(agentContext: AgentContext, recordClass: BaseRecordConstructor): Promise { + public async getAllAsAttributes(agentContext: AgentContext, recordClass: BaseRecordConstructor): Promise { agentContext.config.logger.debug(`Getting all records of type ${recordClass.name}`); const attributes = await this.attributeController.getLocalAttributes({ "@type": "OwnIdentityAttribute", "content.value.@type": "VerifiableCredential" }); - return attributes; + return attributes as OwnIdentityAttribute[]; } public async findByQuery(agentContext: AgentContext, recordClass: BaseRecordConstructor, query: Query, queryOptions?: QueryOptions): Promise { diff --git a/packages/consumption/src/modules/openid4vc/local/Holder.ts b/packages/consumption/src/modules/openid4vc/local/Holder.ts index fac99f5f6..633d908c9 100644 --- a/packages/consumption/src/modules/openid4vc/local/Holder.ts +++ b/packages/consumption/src/modules/openid4vc/local/Holder.ts @@ -50,7 +50,7 @@ export class Holder extends BaseAgent> super(3000, `OpenId4VcHolder ${Math.random().toString()}`, getOpenIdHolderModules(), accountController, attributeController); } - public async getVerifiableCredentials(ids: string[] | undefined): Promise { + public async getVerifiableCredentials(ids: string[] | undefined): Promise { // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion const storageService = this.agent.dependencyManager.resolve(InjectionSymbols.StorageService) as EnmeshedStorageService; const allCredentials = await storageService.getAllAsAttributes(this.agent.context, SdJwtVcRecord); @@ -255,13 +255,12 @@ export class Holder extends BaseAgent> return storedCredentials; } - public async resolveProofRequest(proofRequest: string): Promise { - const resolvedProofRequest = await this.agent.openid4vc.holder.resolveOpenId4VpAuthorizationRequest(proofRequest); - - return resolvedProofRequest; + public async resolveAuthorizationRequest(request: string): Promise { + const resolvedRequest = await this.agent.openid4vc.holder.resolveOpenId4VpAuthorizationRequest(request); + return resolvedRequest; } - public async acceptPresentationRequest(resolvedPresentationRequest: OpenId4VpResolvedAuthorizationRequest): Promise< + public async acceptAuthorizationRequest(resolvedAuthenticationRequest: OpenId4VpResolvedAuthorizationRequest): Promise< | { readonly status: number; readonly body: string | Record | null; @@ -272,15 +271,15 @@ export class Holder extends BaseAgent> } | undefined > { - if (!resolvedPresentationRequest.presentationExchange && !resolvedPresentationRequest.dcql) { + if (!resolvedAuthenticationRequest.presentationExchange && !resolvedAuthenticationRequest.dcql) { throw new Error("Missing presentation exchange or dcql on resolved authorization request"); } // This fix ensures that the credential records which have been loaded here actually do provide the encoded() method // this issue arises as the records are loaded and then communicated to the app as a json object, losing the class prototype - if (resolvedPresentationRequest.presentationExchange) { - for (const requirementKey in resolvedPresentationRequest.presentationExchange.credentialsForRequest.requirements) { - const requirement = resolvedPresentationRequest.presentationExchange.credentialsForRequest.requirements[requirementKey]; + if (resolvedAuthenticationRequest.presentationExchange) { + for (const requirementKey in resolvedAuthenticationRequest.presentationExchange.credentialsForRequest.requirements) { + const requirement = resolvedAuthenticationRequest.presentationExchange.credentialsForRequest.requirements[requirementKey]; for (const submissionEntry of requirement.submissionEntry) { for (const vc of submissionEntry.verifiableCredentials) { if (vc.claimFormat === ClaimFormat.SdJwtDc) { @@ -309,17 +308,17 @@ export class Holder extends BaseAgent> } const submissionResult = await this.agent.openid4vc.holder.acceptOpenId4VpAuthorizationRequest({ - authorizationRequestPayload: resolvedPresentationRequest.authorizationRequestPayload, - presentationExchange: resolvedPresentationRequest.presentationExchange + authorizationRequestPayload: resolvedAuthenticationRequest.authorizationRequestPayload, + presentationExchange: resolvedAuthenticationRequest.presentationExchange ? { credentials: this.agent.openid4vc.holder.selectCredentialsForPresentationExchangeRequest( - resolvedPresentationRequest.presentationExchange.credentialsForRequest + resolvedAuthenticationRequest.presentationExchange.credentialsForRequest ) } : undefined, - dcql: resolvedPresentationRequest.dcql + dcql: resolvedAuthenticationRequest.dcql ? { - credentials: this.agent.openid4vc.holder.selectCredentialsForDcqlRequest(resolvedPresentationRequest.dcql.queryResult) + credentials: this.agent.openid4vc.holder.selectCredentialsForDcqlRequest(resolvedAuthenticationRequest.dcql.queryResult) } : undefined }); diff --git a/packages/runtime-types/src/consumption/AcceptedAuthorizationRequestDTO.ts b/packages/runtime-types/src/consumption/AcceptedAuthorizationRequestDTO.ts new file mode 100644 index 000000000..f7fada0e1 --- /dev/null +++ b/packages/runtime-types/src/consumption/AcceptedAuthorizationRequestDTO.ts @@ -0,0 +1,4 @@ +export interface AcceptAuthorizationRequestDTO { + status: number; + message: string; +} diff --git a/packages/runtime-types/src/consumption/AcceptedProofRequestDTO.ts b/packages/runtime-types/src/consumption/AcceptedProofRequestDTO.ts deleted file mode 100644 index b5098ce9b..000000000 --- a/packages/runtime-types/src/consumption/AcceptedProofRequestDTO.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface AcceptProofRequestDTO { - status: number; - message: string; -} diff --git a/packages/runtime-types/src/consumption/FetchedAuthorizationRequestDTO.ts b/packages/runtime-types/src/consumption/FetchedAuthorizationRequestDTO.ts new file mode 100644 index 000000000..ce97265ea --- /dev/null +++ b/packages/runtime-types/src/consumption/FetchedAuthorizationRequestDTO.ts @@ -0,0 +1,6 @@ +import { VerifiableCredentialDTO } from "./VerifiableCredentialDTO"; + +export interface FetchedAuthorizationRequestDTO { + authorizationRequest: Record; + usedCredentials: VerifiableCredentialDTO[]; +} diff --git a/packages/runtime-types/src/consumption/FetchedProofRequestDTO.ts b/packages/runtime-types/src/consumption/FetchedProofRequestDTO.ts deleted file mode 100644 index a621a223b..000000000 --- a/packages/runtime-types/src/consumption/FetchedProofRequestDTO.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface FetchedProofRequestDTO { - jsonRepresentation: string; -} diff --git a/packages/runtime-types/src/consumption/VerifiableCredentialDTO.ts b/packages/runtime-types/src/consumption/VerifiableCredentialDTO.ts index ff4fe7e2d..aa9042a93 100644 --- a/packages/runtime-types/src/consumption/VerifiableCredentialDTO.ts +++ b/packages/runtime-types/src/consumption/VerifiableCredentialDTO.ts @@ -1,6 +1,6 @@ export interface VerifiableCredentialDTO { - data: string; id: string; + data: string; type: string; displayInformation?: string; key?: string; diff --git a/packages/runtime-types/src/consumption/index.ts b/packages/runtime-types/src/consumption/index.ts index 5a1f6bd76..c9fb6f886 100644 --- a/packages/runtime-types/src/consumption/index.ts +++ b/packages/runtime-types/src/consumption/index.ts @@ -1,9 +1,9 @@ -export * from "./AcceptedProofRequestDTO"; +export * from "./AcceptedAuthorizationRequestDTO"; export * from "./AttributeTagCollectionDTO"; export * from "./CredentialOfferDTO"; export * from "./DraftDTO"; +export * from "./FetchedAuthorizationRequestDTO"; export * from "./FetchedCredentialOfferDTO"; -export * from "./FetchedProofRequestDTO"; export * from "./IdentityMetadataDTO"; export * from "./LocalAttributeDeletionInfoDTO"; export * from "./LocalAttributeDTO"; diff --git a/packages/runtime/src/extensibility/facades/consumption/OpenId4VcFacade.ts b/packages/runtime/src/extensibility/facades/consumption/OpenId4VcFacade.ts index 13e24589c..29d796111 100644 --- a/packages/runtime/src/extensibility/facades/consumption/OpenId4VcFacade.ts +++ b/packages/runtime/src/extensibility/facades/consumption/OpenId4VcFacade.ts @@ -1,27 +1,27 @@ import { ApplicationError, Result } from "@js-soft/ts-utils"; -import { AcceptProofRequestDTO, FetchedCredentialOfferDTO, FetchedProofRequestDTO, VerifiableCredentialDTO } from "@nmshd/runtime-types"; +import { AcceptAuthorizationRequestDTO, FetchedAuthorizationRequestDTO, FetchedCredentialOfferDTO, VerifiableCredentialDTO } from "@nmshd/runtime-types"; import { Inject } from "@nmshd/typescript-ioc"; import { - AcceptProofRequestRequest, - AcceptProofRequestUseCase, + AcceptAuthorizationRequestRequest, + AcceptAuthorizationRequestUseCase, FetchCredentialOfferRequest, FetchCredentialOfferUseCase, FetchedCredentialOfferRequest, - FetchProofRequestRequest, - FetchProofRequestUseCase, + GetVerifiableCredentialsUseCase, + ResolveAuthorizationRequestRequest, + ResolveAuthorizationRequestUseCase, ResolveCredentialOfferRequest, ResolveCredentialOfferUseCase, ResolveFetchedCredentialOfferUseCase } from "../../../useCases"; -import { GetVerifiableCredentialsUseCase } from "../../../useCases/consumption/openid4vc/GetVerifiableCredentialsUseCase"; export class OpenId4VcFacade { public constructor( @Inject private readonly resolveCredentialOfferUseCase: ResolveCredentialOfferUseCase, @Inject private readonly fetchOfferUseCase: FetchCredentialOfferUseCase, @Inject private readonly resolveFetchedOfferUseCase: ResolveFetchedCredentialOfferUseCase, - @Inject private readonly fetchProofRequestUseCase: FetchProofRequestUseCase, - @Inject private readonly accepProofRequestUseCase: AcceptProofRequestUseCase, + @Inject private readonly resolveAuthorizationRequestUseCase: ResolveAuthorizationRequestUseCase, + @Inject private readonly acceptAuthorizationRequestUseCase: AcceptAuthorizationRequestUseCase, @Inject private readonly getVerifiableCredentialsUseCase: GetVerifiableCredentialsUseCase ) {} @@ -37,15 +37,15 @@ export class OpenId4VcFacade { return await this.resolveFetchedOfferUseCase.execute(request); } - public async fetchProofRequest(request: FetchProofRequestRequest): Promise> { - return await this.fetchProofRequestUseCase.execute(request); + public async resolveAuthorizationRequest(request: ResolveAuthorizationRequestRequest): Promise> { + return await this.resolveAuthorizationRequestUseCase.execute(request); } - public async acceptProofRequest(request: AcceptProofRequestRequest): Promise> { - return await this.accepProofRequestUseCase.execute(request); + public async acceptAuthorizationRequest(request: AcceptAuthorizationRequestRequest): Promise> { + return await this.acceptAuthorizationRequestUseCase.execute(request); } - public async getVerifiableCredentials(ids: string[] | undefined): Promise> { + public async getVerifiableCredentials(ids?: string[]): Promise> { return await this.getVerifiableCredentialsUseCase.execute({ ids }); } } diff --git a/packages/runtime/src/useCases/common/Schemas.ts b/packages/runtime/src/useCases/common/Schemas.ts index 2525d180f..ec57ad2ee 100644 --- a/packages/runtime/src/useCases/common/Schemas.ts +++ b/packages/runtime/src/useCases/common/Schemas.ts @@ -16699,19 +16699,19 @@ export const SentNotificationRequest: any = { } } -export const AcceptProofRequestRequest: any = { +export const AcceptAuthorizationRequestRequest: any = { "$schema": "http://json-schema.org/draft-07/schema#", - "$ref": "#/definitions/AcceptProofRequestRequest", + "$ref": "#/definitions/AcceptAuthorizationRequestRequest", "definitions": { - "AcceptProofRequestRequest": { + "AcceptAuthorizationRequestRequest": { "type": "object", "properties": { - "jsonEncodedRequest": { - "type": "string" + "authorizationRequest": { + "type": "object" } }, "required": [ - "jsonEncodedRequest" + "authorizationRequest" ], "additionalProperties": false } @@ -16737,19 +16737,38 @@ export const FetchCredentialOfferRequest: any = { } } -export const FetchProofRequestRequest: any = { +export const GetVerifiableCredentialsRequest: any = { + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/GetVerifiableCredentialsRequest", + "definitions": { + "GetVerifiableCredentialsRequest": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + } + } +} + +export const ResolveAuthorizationRequestRequest: any = { "$schema": "http://json-schema.org/draft-07/schema#", - "$ref": "#/definitions/FetchProofRequestRequest", + "$ref": "#/definitions/ResolveAuthorizationRequestRequest", "definitions": { - "FetchProofRequestRequest": { + "ResolveAuthorizationRequestRequest": { "type": "object", "properties": { - "proofRequestUrl": { + "requestUrl": { "type": "string" } }, "required": [ - "proofRequestUrl" + "requestUrl" ], "additionalProperties": false } @@ -19996,25 +20015,6 @@ export const LoadPeerTokenRequest: any = { } } -export const GetVerifiableCredentialsRequest: any = { - "$schema": "http://json-schema.org/draft-07/schema#", - "$ref": "#/definitions/GetVerifiableCredentialsRequest", - "definitions": { - "GetVerifiableCredentialsRequest": { - "type": "object", - "properties": { - "ids": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - } - } -} - export const CommunicationLanguage: any = { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/CommunicationLanguage", diff --git a/packages/runtime/src/useCases/consumption/openid4vc/AcceptAuthorizationRequest.ts b/packages/runtime/src/useCases/consumption/openid4vc/AcceptAuthorizationRequest.ts new file mode 100644 index 000000000..95b1bed56 --- /dev/null +++ b/packages/runtime/src/useCases/consumption/openid4vc/AcceptAuthorizationRequest.ts @@ -0,0 +1,30 @@ +import { OpenId4VpResolvedAuthorizationRequest } from "@credo-ts/openid4vc"; +import { Result } from "@js-soft/ts-utils"; +import { OpenId4VcController } from "@nmshd/consumption"; +import { AcceptAuthorizationRequestDTO } from "@nmshd/runtime-types"; +import { Inject } from "@nmshd/typescript-ioc"; +import { SchemaRepository, SchemaValidator, UseCase } from "../../common"; + +export interface AcceptAuthorizationRequestRequest { + authorizationRequest: Record; +} + +class Validator extends SchemaValidator { + public constructor(@Inject schemaRepository: SchemaRepository) { + super(schemaRepository.getSchema("AcceptAuthorizationRequestRequest")); + } +} + +export class AcceptAuthorizationRequestUseCase extends UseCase { + public constructor( + @Inject private readonly openId4VcContoller: OpenId4VcController, + @Inject validator: Validator + ) { + super(validator); + } + + protected override async executeInternal(request: AcceptAuthorizationRequestRequest): Promise> { + const result = await this.openId4VcContoller.acceptAuthorizationRequest(request.authorizationRequest as OpenId4VpResolvedAuthorizationRequest); + return Result.ok({ status: result.status, message: JSON.stringify(result.message) }); + } +} diff --git a/packages/runtime/src/useCases/consumption/openid4vc/AcceptProofRequestUseCase.ts b/packages/runtime/src/useCases/consumption/openid4vc/AcceptProofRequestUseCase.ts deleted file mode 100644 index bba2b291d..000000000 --- a/packages/runtime/src/useCases/consumption/openid4vc/AcceptProofRequestUseCase.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Result } from "@js-soft/ts-utils"; -import { OpenId4VcController } from "@nmshd/consumption"; -import { AcceptProofRequestDTO } from "@nmshd/runtime-types"; -import { Inject } from "@nmshd/typescript-ioc"; -import { SchemaRepository, SchemaValidator, UseCase } from "../../common"; - -export interface AcceptProofRequestRequest { - jsonEncodedRequest: string; -} - -class Validator extends SchemaValidator { - public constructor(@Inject schemaRepository: SchemaRepository) { - super(schemaRepository.getSchema("AcceptProofRequestRequest")); - } -} - -export class AcceptProofRequestUseCase extends UseCase { - public constructor( - @Inject private readonly openId4VcContoller: OpenId4VcController, - @Inject validator: Validator - ) { - super(validator); - } - - protected override async executeInternal(request: AcceptProofRequestRequest): Promise> { - const result = await this.openId4VcContoller.acceptProofRequest(request.jsonEncodedRequest); - return Result.ok({ status: result.status, message: JSON.stringify(result.message) } as AcceptProofRequestDTO); - } -} diff --git a/packages/runtime/src/useCases/consumption/openid4vc/FetchCredentialOfferUseCase.ts b/packages/runtime/src/useCases/consumption/openid4vc/FetchCredentialOffer.ts similarity index 100% rename from packages/runtime/src/useCases/consumption/openid4vc/FetchCredentialOfferUseCase.ts rename to packages/runtime/src/useCases/consumption/openid4vc/FetchCredentialOffer.ts diff --git a/packages/runtime/src/useCases/consumption/openid4vc/FetchProofRequestUseCase.ts b/packages/runtime/src/useCases/consumption/openid4vc/FetchProofRequestUseCase.ts deleted file mode 100644 index 9f64d80eb..000000000 --- a/packages/runtime/src/useCases/consumption/openid4vc/FetchProofRequestUseCase.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Result } from "@js-soft/ts-utils"; -import { OpenId4VcController } from "@nmshd/consumption"; -import { FetchedProofRequestDTO } from "@nmshd/runtime-types"; -import { Inject } from "@nmshd/typescript-ioc"; -import { SchemaRepository, SchemaValidator, UseCase } from "../../common"; - -export interface FetchProofRequestRequest { - proofRequestUrl: string; -} - -class Validator extends SchemaValidator { - public constructor(@Inject schemaRepository: SchemaRepository) { - super(schemaRepository.getSchema("FetchProofRequestRequest")); - } -} - -export class FetchProofRequestUseCase extends UseCase { - public constructor( - @Inject private readonly openId4VcContoller: OpenId4VcController, - @Inject validator: Validator - ) { - super(validator); - } - - protected override async executeInternal(request: FetchProofRequestRequest): Promise> { - const result = await this.openId4VcContoller.fetchProofRequest(request.proofRequestUrl); - return Result.ok({ jsonRepresentation: result.data } as FetchedProofRequestDTO); - } -} diff --git a/packages/runtime/src/useCases/consumption/openid4vc/GetVerifiableCredentialsUseCase.ts b/packages/runtime/src/useCases/consumption/openid4vc/GetVerifiableCredentials.ts similarity index 94% rename from packages/runtime/src/useCases/consumption/openid4vc/GetVerifiableCredentialsUseCase.ts rename to packages/runtime/src/useCases/consumption/openid4vc/GetVerifiableCredentials.ts index 725d55578..55beb77d7 100644 --- a/packages/runtime/src/useCases/consumption/openid4vc/GetVerifiableCredentialsUseCase.ts +++ b/packages/runtime/src/useCases/consumption/openid4vc/GetVerifiableCredentials.ts @@ -24,6 +24,6 @@ export class GetVerifiableCredentialsUseCase extends UseCase> { const credentials = await this.openId4VcContoller.getVerifiableCredentials(request.ids); - return Result.ok(credentials as VerifiableCredentialDTO[]); + return Result.ok(credentials); } } diff --git a/packages/runtime/src/useCases/consumption/openid4vc/ResolveAuthorizationRequest.ts b/packages/runtime/src/useCases/consumption/openid4vc/ResolveAuthorizationRequest.ts new file mode 100644 index 000000000..fd2b07e80 --- /dev/null +++ b/packages/runtime/src/useCases/consumption/openid4vc/ResolveAuthorizationRequest.ts @@ -0,0 +1,30 @@ +import { Result } from "@js-soft/ts-utils"; +import { OpenId4VcController } from "@nmshd/consumption"; +import { FetchedAuthorizationRequestDTO } from "@nmshd/runtime-types"; +import { Inject } from "@nmshd/typescript-ioc"; +import { SchemaRepository, SchemaValidator, UseCase } from "../../common"; + +export interface ResolveAuthorizationRequestRequest { + requestUrl: string; +} + +class Validator extends SchemaValidator { + public constructor(@Inject schemaRepository: SchemaRepository) { + super(schemaRepository.getSchema("ResolveAuthorizationRequestRequest")); + } +} + +export class ResolveAuthorizationRequestUseCase extends UseCase { + public constructor( + @Inject private readonly openId4VcContoller: OpenId4VcController, + @Inject validator: Validator + ) { + super(validator); + } + + protected override async executeInternal(request: ResolveAuthorizationRequestRequest): Promise> { + const result = await this.openId4VcContoller.resolveAuthorizationRequest(request.requestUrl); + + return Result.ok({ authorizationRequest: result.authorizationRequest, usedCredentials: result.usedCredentials }); + } +} diff --git a/packages/runtime/src/useCases/consumption/openid4vc/ResolveCredentialOfferUseCase.ts b/packages/runtime/src/useCases/consumption/openid4vc/ResolveCredentialOffer.ts similarity index 100% rename from packages/runtime/src/useCases/consumption/openid4vc/ResolveCredentialOfferUseCase.ts rename to packages/runtime/src/useCases/consumption/openid4vc/ResolveCredentialOffer.ts diff --git a/packages/runtime/src/useCases/consumption/openid4vc/ResolveFetchedCredentialUseCase.ts b/packages/runtime/src/useCases/consumption/openid4vc/ResolveFetchedCredential.ts similarity index 100% rename from packages/runtime/src/useCases/consumption/openid4vc/ResolveFetchedCredentialUseCase.ts rename to packages/runtime/src/useCases/consumption/openid4vc/ResolveFetchedCredential.ts diff --git a/packages/runtime/src/useCases/consumption/openid4vc/index.ts b/packages/runtime/src/useCases/consumption/openid4vc/index.ts index 63fac8183..9d19e641b 100644 --- a/packages/runtime/src/useCases/consumption/openid4vc/index.ts +++ b/packages/runtime/src/useCases/consumption/openid4vc/index.ts @@ -1,5 +1,6 @@ -export * from "./AcceptProofRequestUseCase"; -export * from "./FetchCredentialOfferUseCase"; -export * from "./FetchProofRequestUseCase"; -export * from "./ResolveCredentialOfferUseCase"; -export * from "./ResolveFetchedCredentialUseCase"; +export * from "./AcceptAuthorizationRequest"; +export * from "./FetchCredentialOffer"; +export * from "./GetVerifiableCredentials"; +export * from "./ResolveAuthorizationRequest"; +export * from "./ResolveCredentialOffer"; +export * from "./ResolveFetchedCredential"; diff --git a/packages/runtime/test/consumption/openid4vc.test.ts b/packages/runtime/test/consumption/openid4vc.test.ts index 9be73d6fd..92b9acbb4 100644 --- a/packages/runtime/test/consumption/openid4vc.test.ts +++ b/packages/runtime/test/consumption/openid4vc.test.ts @@ -1,3 +1,4 @@ +import { OpenId4VpResolvedAuthorizationRequest } from "@credo-ts/openid4vc"; import axios, { AxiosInstance } from "axios"; import path from "path"; import { DockerComposeEnvironment, StartedDockerComposeEnvironment, Wait } from "testcontainers"; @@ -69,7 +70,7 @@ describe("OpenID4VCI and OpenID4VCP", () => { }); expect(acceptanceResult).toBeSuccessful(); expect(typeof acceptanceResult.value.id).toBe("string"); - }, 10000000); + }); test("should be able to process a given credential presentation", async () => { // Ensure the first test has completed @@ -109,36 +110,32 @@ describe("OpenID4VCI and OpenID4VCP", () => { expect(response.status).toBe(200); const responseData = await response.data; - const result = await consumptionServices.openId4Vc.fetchProofRequest({ - proofRequestUrl: responseData.result.presentationRequest - }); - const jsonRepresentation = result.value.jsonRepresentation; + const result = await consumptionServices.openId4Vc.resolveAuthorizationRequest({ requestUrl: responseData.result.presentationRequest }); + expect(result.value.usedCredentials).toHaveLength(1); - const proofRequest = JSON.parse(jsonRepresentation); - expect(proofRequest.presentationExchange.credentialsForRequest.areRequirementsSatisfied).toBe(true); + const request = result.value.authorizationRequest as OpenId4VpResolvedAuthorizationRequest; + expect(request.presentationExchange!.credentialsForRequest.areRequirementsSatisfied).toBe(true); - const presentationResult = await consumptionServices.openId4Vc.acceptProofRequest({ - jsonEncodedRequest: jsonRepresentation - }); + const presentationResult = await consumptionServices.openId4Vc.acceptAuthorizationRequest({ authorizationRequest: result.value.authorizationRequest }); expect(presentationResult).toBeSuccessful(); expect(presentationResult.value.status).toBe(200); - }, 10000000); + }); - test("getting all verifiable credentials should not return an empy list", async () => { + test("getting all verifiable credentials should not return an empty list", async () => { // Ensure the first test has completed expect(credentialOfferUrl).toBeDefined(); - const acceptanceResult = await consumptionServices.openId4Vc.getVerifiableCredentials(undefined); + const acceptanceResult = await consumptionServices.openId4Vc.getVerifiableCredentials(); expect(acceptanceResult).toBeSuccessful(); expect(acceptanceResult.value.length).toBeGreaterThan(0); - }, 10000000); + }); test("getting the earlier created verifiable credential by id should return exactly one credential", async () => { // Ensure the first test has completed expect(credentialOfferUrl).toBeDefined(); - const allCredentialsResult = await consumptionServices.openId4Vc.getVerifiableCredentials(undefined); + const allCredentialsResult = await consumptionServices.openId4Vc.getVerifiableCredentials(); expect(allCredentialsResult).toBeSuccessful(); expect(allCredentialsResult.value.length).toBeGreaterThan(0); @@ -147,7 +144,7 @@ describe("OpenID4VCI and OpenID4VCP", () => { expect(singleCredentialResult).toBeSuccessful(); expect(singleCredentialResult.value).toHaveLength(1); expect(singleCredentialResult.value[0].id).toBe(firstCredentialId); - }, 10000000); + }); }); async function startOid4VcComposeStack() {