diff --git a/ts/features/itwallet/common/utils/itwAttestationUtils.ts b/ts/features/itwallet/common/utils/itwAttestationUtils.ts index a28f06739b5..985163f6dfb 100644 --- a/ts/features/itwallet/common/utils/itwAttestationUtils.ts +++ b/ts/features/itwallet/common/utils/itwAttestationUtils.ts @@ -23,6 +23,7 @@ export const getIntegrityHardwareKeyTag = async (): Promise => /** * Register a new wallet instance with hardwareKeyTag. * @param hardwareKeyTag - the hardware key tag of the integrity Context + * @param sessionToken - the session token to use for the API calls */ export const registerWalletInstance = async ( hardwareKeyTag: string, @@ -42,6 +43,7 @@ export const registerWalletInstance = async ( /** * Getter for the wallet attestation binded to the wallet instance created with the given hardwareKeyTag. * @param hardwareKeyTag - the hardware key tag of the wallet instance + * @param sessionToken - the session token to use for the API calls * @return the wallet attestation and the related key tag */ export const getAttestation = async ( @@ -81,6 +83,7 @@ export const isWalletInstanceAttestationValid = ( * Get the wallet instance status from the Wallet Provider. * This operation is more lightweight than getting a new attestation to check the status. * @param hardwareKeyTag The hardware key tag used to create the wallet instance + * @param sessionToken The session token to use for the API calls */ export const getWalletInstanceStatus = ( hardwareKeyTag: string, diff --git a/ts/features/itwallet/machine/eid/__tests__/machine.test.ts b/ts/features/itwallet/machine/eid/__tests__/machine.test.ts index c7d51a9c7ab..751df57822b 100644 --- a/ts/features/itwallet/machine/eid/__tests__/machine.test.ts +++ b/ts/features/itwallet/machine/eid/__tests__/machine.test.ts @@ -40,6 +40,7 @@ describe("itwEidIssuanceMachine", () => { const navigateToNfcInstructionsScreen = jest.fn(); const navigateToCieIdLoginScreen = jest.fn(); const storeIntegrityKeyTag = jest.fn(); + const cleanupIntegrityKeyTag = jest.fn(); const storeWalletInstanceAttestation = jest.fn(); const storeEidCredential = jest.fn(); const closeIssuance = jest.fn(); @@ -82,6 +83,7 @@ describe("itwEidIssuanceMachine", () => { navigateToNfcInstructionsScreen, navigateToCieIdLoginScreen, storeIntegrityKeyTag, + cleanupIntegrityKeyTag, storeWalletInstanceAttestation, storeEidCredential, closeIssuance, @@ -982,4 +984,49 @@ describe("itwEidIssuanceMachine", () => { expect(actor.getSnapshot().value).toStrictEqual("Idle"); }); + + it("should cleanup integrity key tag and fail when obtaining Wallet Instance Attestation fails", async () => { + const actor = createActor(mockedMachine); + actor.start(); + + await waitFor(() => expect(onInit).toHaveBeenCalledTimes(1)); + + expect(actor.getSnapshot().value).toStrictEqual("Idle"); + expect(actor.getSnapshot().context).toStrictEqual(InitialContext); + expect(actor.getSnapshot().tags).toStrictEqual(new Set()); + + /** + * Start eID issuance + */ + actor.send({ type: "start" }); + + expect(actor.getSnapshot().value).toStrictEqual("TosAcceptance"); + expect(actor.getSnapshot().tags).toStrictEqual(new Set()); + expect(navigateToTosScreen).toHaveBeenCalledTimes(1); + + /** + * Accept TOS and request WIA + */ + + createWalletInstance.mockImplementation(() => + Promise.resolve(T_INTEGRITY_KEY) + ); + getWalletAttestation.mockImplementation(() => Promise.reject({})); // Simulate failure + isSessionExpired.mockImplementation(() => false); // Session not expired + + actor.send({ type: "accept-tos" }); + + expect(actor.getSnapshot().value).toStrictEqual("WalletInstanceCreation"); + expect(actor.getSnapshot().tags).toStrictEqual(new Set([ItwTags.Loading])); + + await waitFor(() => expect(createWalletInstance).toHaveBeenCalledTimes(1)); + await waitFor(() => expect(getWalletAttestation).toHaveBeenCalledTimes(1)); + + // Wallet Instance Attestation failure triggers cleanupIntegrityKeyTag + expect(cleanupIntegrityKeyTag).toHaveBeenCalledTimes(1); + + // Check that the machine transitions to Failure state + expect(actor.getSnapshot().value).toStrictEqual("Failure"); + expect(actor.getSnapshot().tags).toStrictEqual(new Set()); + }); }); diff --git a/ts/features/itwallet/machine/eid/actions.ts b/ts/features/itwallet/machine/eid/actions.ts index 9b84d7a1e23..2572a537d9f 100644 --- a/ts/features/itwallet/machine/eid/actions.ts +++ b/ts/features/itwallet/machine/eid/actions.ts @@ -9,7 +9,10 @@ import { checkCurrentSession } from "../../../../store/actions/authentication"; import { useIOStore } from "../../../../store/hooks"; import { assert } from "../../../../utils/assert"; import { itwCredentialsStore } from "../../credentials/store/actions"; -import { itwStoreIntegrityKeyTag } from "../../issuance/store/actions"; +import { + itwRemoveIntegrityKeyTag, + itwStoreIntegrityKeyTag +} from "../../issuance/store/actions"; import { itwLifecycleStateUpdated, itwLifecycleWalletReset @@ -168,6 +171,11 @@ export const createEidIssuanceActionsImplementation = ( store.dispatch(itwStoreIntegrityKeyTag(context.integrityKeyTag)); }, + cleanupIntegrityKeyTag: () => { + // Remove the integrity key tag from the store + store.dispatch(itwRemoveIntegrityKeyTag()); + }, + storeWalletInstanceAttestation: ({ context }: ActionArgs) => { diff --git a/ts/features/itwallet/machine/eid/machine.ts b/ts/features/itwallet/machine/eid/machine.ts index 3da95b4605c..1d381db258f 100644 --- a/ts/features/itwallet/machine/eid/machine.ts +++ b/ts/features/itwallet/machine/eid/machine.ts @@ -43,6 +43,7 @@ export const itwEidIssuanceMachine = setup({ navigateToNfcInstructionsScreen: notImplemented, navigateToWalletRevocationScreen: notImplemented, storeIntegrityKeyTag: notImplemented, + cleanupIntegrityKeyTag: notImplemented, storeWalletInstanceAttestation: notImplemented, storeEidCredential: notImplemented, closeIssuance: notImplemented, @@ -225,7 +226,7 @@ export const itwEidIssuanceMachine = setup({ target: "#itwEidIssuanceMachine.TosAcceptance" }, { - actions: "setFailure", + actions: ["setFailure", "cleanupIntegrityKeyTag"], target: "#itwEidIssuanceMachine.Failure" } ]