From d2c6c750b57a80561e60c55402757d4629374f98 Mon Sep 17 00:00:00 2001 From: "A.G.J. Cate" Date: Wed, 13 Nov 2024 16:05:52 +0100 Subject: [PATCH] feat: added review contact state when contact has low level of trust --- .../oid4vci-holder/src/agent/OID4VCIHolder.ts | 6 + .../src/machine/oid4vciMachine.ts | 103 ++++++++++++------ .../src/types/IOID4VCIHolder.ts | 4 +- 3 files changed, 80 insertions(+), 33 deletions(-) diff --git a/packages/oid4vci-holder/src/agent/OID4VCIHolder.ts b/packages/oid4vci-holder/src/agent/OID4VCIHolder.ts index 084915b4e..01f375b81 100644 --- a/packages/oid4vci-holder/src/agent/OID4VCIHolder.ts +++ b/packages/oid4vci-holder/src/agent/OID4VCIHolder.ts @@ -770,6 +770,12 @@ export class OID4VCIHolder implements IAgentPlugin { .filter((identity) => identity.roles.includes(CredentialRole.ISSUER)) .map((identity) => identity.identifier.correlationId)[0] + // we check for issuer branding as adding an identity might also trigger storing the issuer branding + const branding = await context.agent.ibGetIssuerBranding({ filter: [{ issuerCorrelationId }] }) + if (branding.length > 0) { + return + } + await context.agent.ibAddIssuerBranding({ localeBranding: issuerBranding as Array, issuerCorrelationId, diff --git a/packages/oid4vci-holder/src/machine/oid4vciMachine.ts b/packages/oid4vci-holder/src/machine/oid4vciMachine.ts index 0c43cfefd..038ce2cff 100644 --- a/packages/oid4vci-holder/src/machine/oid4vciMachine.ts +++ b/packages/oid4vci-holder/src/machine/oid4vciMachine.ts @@ -45,6 +45,11 @@ const oid4vciHasContactGuard = (_ctx: OID4VCIMachineContext, _event: OID4VCIMach return contact !== undefined } +const oid4vciContactHasLowTrustGuard = (_ctx: OID4VCIMachineContext, _event: OID4VCIMachineEventTypes): boolean => { + const { contact, trustedAnchors } = _ctx + return contact !== undefined && trustedAnchors !== undefined && trustedAnchors.length === 0 +} + const oid4vciCredentialsToSelectRequiredGuard = (_ctx: OID4VCIMachineContext, _event: OID4VCIMachineEventTypes): boolean => { const { credentialToSelectFrom } = _ctx return credentialToSelectFrom && credentialToSelectFrom.length > 1 @@ -81,8 +86,8 @@ const oid4vciHasSelectedCredentialsGuard = (_ctx: OID4VCIMachineContext, _event: const oid4vciIsOIDFOriginGuard = (_ctx: OID4VCIMachineContext, _event: OID4VCIMachineEventTypes): boolean => { // TODO in the future we need to establish if a origin is a IDF origin. So we need to check if this metadata is on the well-known location - const { trustAnchors, contact } = _ctx - return trustAnchors.length > 0 && contact === undefined + const { trustAnchors } = _ctx + return trustAnchors.length > 0 } const oid4vciNoAuthorizationGuard = (ctx: OID4VCIMachineContext, _event: OID4VCIMachineEventTypes): boolean => { @@ -152,7 +157,8 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach | { type: OID4VCIMachineGuards.createContactGuard } | { type: OID4VCIMachineGuards.hasSelectedCredentialsGuard } | { type: OID4VCIMachineGuards.hasAuthorizationResponse } - | { type: OID4VCIMachineGuards.oid4vciIsOIDFOriginGuard }, + | { type: OID4VCIMachineGuards.isOIDFOriginGuard } + | { type: OID4VCIMachineGuards.contactHasLowTrustGuard }, services: {} as { [OID4VCIMachineServices.start]: { data: StartResult @@ -265,17 +271,48 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach id: OID4VCIMachineStates.getIssuerBranding, invoke: { src: OID4VCIMachineServices.getIssuerBranding, + onDone: [ + { + target: OID4VCIMachineStates.getFederationTrust, + cond: OID4VCIMachineGuards.isOIDFOriginGuard, + actions: assign({ + issuerBranding: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent>) => _event.data + }) + }, + { + target: OID4VCIMachineStates.transitionFromSetup, + actions: assign({ + issuerBranding: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent>) => _event.data + }) + } + ], + onError: { + target: OID4VCIMachineStates.handleError, + actions: assign({ + error: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent): ErrorDetails => ({ + title: translate('oid4vci_machine_retrieve_issuer_branding_error_title'), + message: _event.data.message, + stack: _event.data.stack, + }), + }), + }, + }, + }, + [OID4VCIMachineStates.getFederationTrust]: { + id: OID4VCIMachineStates.getFederationTrust, + invoke: { + src: OID4VCIMachineServices.getFederationTrust, onDone: { target: OID4VCIMachineStates.transitionFromSetup, actions: assign({ - issuerBranding: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent>) => _event.data + trustedAnchors: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent>) => _event.data }) }, onError: { target: OID4VCIMachineStates.handleError, actions: assign({ error: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent): ErrorDetails => ({ - title: translate('oid4vci_machine_retrieve_issuer_branding_error_title'), + title: translate('oid4vci_machine_retrieve_federation_trust_error_title'), message: _event.data.message, stack: _event.data.stack, }), @@ -286,15 +323,14 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach [OID4VCIMachineStates.transitionFromSetup]: { id: OID4VCIMachineStates.transitionFromSetup, always: [ - // TODO improve getFederationTrust machine logic and where we call this in the machine. we only need this for new contacts, as it is only displayed on the add contact screen - { - target: OID4VCIMachineStates.getFederationTrust, - cond: OID4VCIMachineGuards.oid4vciIsOIDFOriginGuard - }, { target: OID4VCIMachineStates.addContact, cond: OID4VCIMachineGuards.hasNoContactGuard, }, + { + target: OID4VCIMachineStates.reviewContact, + cond: OID4VCIMachineGuards.contactHasLowTrustGuard, + }, { target: OID4VCIMachineStates.selectCredentials, cond: OID4VCIMachineGuards.credentialsToSelectRequiredGuard, @@ -317,28 +353,6 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach }, }, }, - [OID4VCIMachineStates.getFederationTrust]: { - id: OID4VCIMachineStates.getFederationTrust, - invoke: { - src: OID4VCIMachineServices.getFederationTrust, - onDone: { - target: OID4VCIMachineStates.addContact, - actions: assign({ - trustedAnchors: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent>) => _event.data - }) - }, - onError: { - target: OID4VCIMachineStates.handleError, - actions: assign({ - error: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent): ErrorDetails => ({ - title: translate('oid4vci_machine_retrieve_federation_trust_error_title'), - message: _event.data.message, - stack: _event.data.stack, - }), - }), - }, - }, - }, [OID4VCIMachineStates.addContact]: { id: OID4VCIMachineStates.addContact, initial: OID4VCIMachineAddContactStates.idle, @@ -371,6 +385,20 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach }, }, }, + [OID4VCIMachineStates.reviewContact]: { + id: OID4VCIMachineStates.reviewContact, + on: { + [OID4VCIMachineEvents.NEXT]: { + target: OID4VCIMachineStates.transitionFromContactSetup, + }, + [OID4VCIMachineEvents.DECLINE]: { + target: OID4VCIMachineStates.declined, + }, + [OID4VCIMachineEvents.PREVIOUS]: { + target: OID4VCIMachineStates.aborted, + }, + }, + }, [OID4VCIMachineStates.storeIssuerBranding]: { id: OID4VCIMachineStates.storeIssuerBranding, invoke: { @@ -585,6 +613,16 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach onDone: { target: OID4VCIMachineStates.reviewCredentials, }, + onError: { + target: OID4VCIMachineStates.handleError, + actions: assign({ + error: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent): ErrorDetails => ({ + title: translate('oid4vci_machine_store_issuer_branding_error_title'), + message: _event.data.message, + stack: _event.data.stack, + }), + }), + }, }, }, [OID4VCIMachineStates.reviewCredentials]: { @@ -690,6 +728,7 @@ export class OID4VCIMachine { oid4vciNoAuthorizationGuard, oid4vciHasAuthorizationResponse, oid4vciIsOIDFOriginGuard, + oid4vciContactHasLowTrustGuard, ...opts?.guards, }, }), diff --git a/packages/oid4vci-holder/src/types/IOID4VCIHolder.ts b/packages/oid4vci-holder/src/types/IOID4VCIHolder.ts index 463bf6708..cb751a659 100644 --- a/packages/oid4vci-holder/src/types/IOID4VCIHolder.ts +++ b/packages/oid4vci-holder/src/types/IOID4VCIHolder.ts @@ -235,6 +235,7 @@ export enum OID4VCIMachineStates { getContact = 'getContact', transitionFromSetup = 'transitionFromSetup', getFederationTrust = 'getFederationTrust', + reviewContact = 'reviewContact', addContact = 'addContact', getIssuerBranding = 'getIssuerBranding', storeIssuerBranding = 'storeIssuerBranding', @@ -363,7 +364,8 @@ export enum OID4VCIMachineGuards { verificationCodeGuard = 'oid4vciVerificationCodeGuard', createContactGuard = 'oid4vciCreateContactGuard', hasSelectedCredentialsGuard = 'oid4vciHasSelectedCredentialsGuard', - oid4vciIsOIDFOriginGuard = 'oid4vciIsOIDFOriginGuard', + isOIDFOriginGuard = 'oid4vciIsOIDFOriginGuard', + contactHasLowTrustGuard = 'oid4vciContactHasLowTrustGuard' } export enum OID4VCIMachineServices {