From 5aaad86e628202c583c6314ee0f18ff60929bdd1 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Wed, 4 Dec 2024 11:26:32 +0100 Subject: [PATCH] fix: issue with ausweis sdk when setting up pid later (#255) Signed-off-by: Timo Glastra Co-authored-by: Berend Sliedrecht <61358536+berendsliedrecht@users.noreply.github.com> --- apps/easypid/README.md | 5 ++ .../features/onboarding/onboardingContext.tsx | 5 +- .../screens/id-card-requested-attributes.tsx | 2 +- .../src/features/pid/FunkePidSetupScreen.tsx | 15 +++--- .../src/use-cases/ReceivePidUseCaseCFlow.ts | 11 ++-- .../src/use-cases/ReceivePidUseCaseFlow.ts | 54 ++++++++++++++++++- 6 files changed, 73 insertions(+), 19 deletions(-) diff --git a/apps/easypid/README.md b/apps/easypid/README.md index 173546fa..ba73c80d 100644 --- a/apps/easypid/README.md +++ b/apps/easypid/README.md @@ -382,6 +382,11 @@ The following standards and specifications were implemented. ### Phase 2 +#### 04-12-2024 + +**Wallet** +- Fixed an issue where the PID setup would get stuck if you skipped it during onboarding [commit](https://github.com/animo/openid4vc-playground-funke/commit/65178e776bc421b9ca413542ea0e86db4ad1ead4) + #### 28-11-2024 **Playground** diff --git a/apps/easypid/src/features/onboarding/onboardingContext.tsx b/apps/easypid/src/features/onboarding/onboardingContext.tsx index b902258f..2e41c15c 100644 --- a/apps/easypid/src/features/onboarding/onboardingContext.tsx +++ b/apps/easypid/src/features/onboarding/onboardingContext.tsx @@ -190,13 +190,16 @@ export function OnboardingContextProvider({ }, [currentStepName]) const finishOnboarding = useCallback(() => { + // We don't need to handle the error if it's not active, but it's important we cancel + receivePidUseCase?.cancelIdCardScanning().catch(() => {}) + setHasFinishedOnboarding(true) // The Onboarding fades out based on the mmkv value // Wait 500ms before navigating to home setTimeout(() => { router.replace('/') }, 500) - }, [router, setHasFinishedOnboarding]) + }, [router, setHasFinishedOnboarding, receivePidUseCase]) const onPinEnter = async (pin: string) => { setWalletPin(pin) diff --git a/apps/easypid/src/features/onboarding/screens/id-card-requested-attributes.tsx b/apps/easypid/src/features/onboarding/screens/id-card-requested-attributes.tsx index 8c1df83b..91213616 100644 --- a/apps/easypid/src/features/onboarding/screens/id-card-requested-attributes.tsx +++ b/apps/easypid/src/features/onboarding/screens/id-card-requested-attributes.tsx @@ -1,7 +1,7 @@ import { bdrPidCredentialDisplay, bdrPidIssuerDisplay } from '@easypid/use-cases/bdrPidMetadata' +import { CardWithAttributes } from '@package/app' import { Button, HeroIcons, Paragraph, ScrollView, YStack } from '@package/ui' import { sanitizeString } from '@package/utils' -import { CardWithAttributes } from 'packages/app/src' import { useState } from 'react' interface OnboardingIdCardRequestedAttributesProps { diff --git a/apps/easypid/src/features/pid/FunkePidSetupScreen.tsx b/apps/easypid/src/features/pid/FunkePidSetupScreen.tsx index d604f2a7..be05f48d 100644 --- a/apps/easypid/src/features/pid/FunkePidSetupScreen.tsx +++ b/apps/easypid/src/features/pid/FunkePidSetupScreen.tsx @@ -170,13 +170,6 @@ export function FunkePidSetupScreen() { } const onWalletPinEnter = async (pin: string) => { - // FIXME: We need to check if the pin is correct, but wallet is not locked. - // PIN is also not used now, as we only do C flow. - - // await secureUnlock.unlockUsingPin(pin).then(() => { - // setWalletPin(pin) - // }) - // If pin is simulator pin we require the user to retry so that second time // they can set the real pin const isSimulatorPinCode = pin === SIMULATOR_PIN @@ -211,6 +204,12 @@ export function FunkePidSetupScreen() { const onStart = (shouldUseCloudHsm: boolean) => setShouldUseCloudHsm(shouldUseCloudHsm) const onIdCardPinEnter = (pin: string) => setIdCardPin(pin) + const onCancel = useCallback(() => { + // We just want to make sure to cancel, don't care about the result + void receivePidUseCase?.cancelIdCardScanning().catch(() => {}) + + pushToWallet() + }, [receivePidUseCase, pushToWallet]) const onStartScanning = async () => { if (receivePidUseCase?.state !== 'id-card-auth') { @@ -449,7 +448,7 @@ export function FunkePidSetupScreen() { title: 'Stop ID Setup?', description: 'If you stop, you can do the setup later.', }} - onCancel={pushToWallet} + onCancel={onCancel} /> ) } diff --git a/apps/easypid/src/use-cases/ReceivePidUseCaseCFlow.ts b/apps/easypid/src/use-cases/ReceivePidUseCaseCFlow.ts index bd1b9269..dae0ee58 100644 --- a/apps/easypid/src/use-cases/ReceivePidUseCaseCFlow.ts +++ b/apps/easypid/src/use-cases/ReceivePidUseCaseCFlow.ts @@ -4,7 +4,6 @@ import { BiometricAuthenticationError, OpenId4VciAuthorizationFlow, type SdJwtVcRecord, - getCredentialCategoryMetadata, receiveCredentialFromOpenId4VciOffer, resolveOpenId4VciOffer, setCredentialCategoryMetadata, @@ -15,12 +14,7 @@ import { import { getShouldUseCloudHsm } from '../features/onboarding/useShouldUseCloudHsm' import { ReceivePidUseCaseFlow, type ReceivePidUseCaseFlowOptions } from './ReceivePidUseCaseFlow' import { C_PRIME_SD_JWT_MDOC_OFFER } from './bdrPidIssuerOffers' -import { - bdrPidCredentialDisplay, - bdrPidIssuerDisplay, - bdrPidOpenId4VcMetadata, - bdrPidSdJwtTypeMetadata, -} from './bdrPidMetadata' +import { bdrPidOpenId4VcMetadata, bdrPidSdJwtTypeMetadata } from './bdrPidMetadata' export class ReceivePidUseCaseCFlow extends ReceivePidUseCaseFlow { public static async initialize(options: ReceivePidUseCaseFlowOptions) { @@ -53,7 +47,8 @@ export class ReceivePidUseCaseCFlow extends ReceivePidUseCaseFlow { resolved.resolvedAuthorizationRequest, resolved.resolvedCredentialOffer ) - authFlow.startAuthFlow() + // We handle the error differently + authFlow.startAuthFlow().catch(() => {}) const accessRights = await authFlow.accessRights authFlow.options.onStateChange?.('id-card-auth') return { authFlow, accessRights } diff --git a/apps/easypid/src/use-cases/ReceivePidUseCaseFlow.ts b/apps/easypid/src/use-cases/ReceivePidUseCaseFlow.ts index 4e4022b2..50f27667 100644 --- a/apps/easypid/src/use-cases/ReceivePidUseCaseFlow.ts +++ b/apps/easypid/src/use-cases/ReceivePidUseCaseFlow.ts @@ -1,4 +1,10 @@ -import { AusweisAuthFlow, type AusweisAuthFlowOptions, sendCommand } from '@animo-id/expo-ausweis-sdk' +import { + AusweisAuthFlow, + type AusweisAuthFlowOptions, + addMessageListener, + initializeSdk, + sendCommand, +} from '@animo-id/expo-ausweis-sdk' import type { MdocRecord } from '@credo-ts/core' import type { AppAgent } from '@easypid/agent' import type { @@ -165,11 +171,57 @@ export abstract class ReceivePidUseCaseFlow { } } + /** + * We always try to gracefully shut the auth flow down + * but somtimes due to an error it may not be the case + * we make sure to always clean running auth flow before we + * start a new one + */ + private async cancelPotentiallyAbandonedAuthFlow() { + await initializeSdk() + + const cancelPromise = new Promise((resolve, reject) => { + let hasCancelled = false + const subscription = addMessageListener((message) => { + // Auth flow is now cancelled + if (message.msg === 'AUTH' && message.result?.reason === 'User_Cancelled') { + subscription.remove() + resolve(undefined) + return + } + + if (message.msg === 'STATUS' && !hasCancelled) { + // Auth flow is active, we need to cancel + if (message.workflow === 'AUTH') { + hasCancelled = true + sendCommand({ cmd: 'CANCEL' }) + return + } + + // Auth flow is not active, no need to cancel + subscription.remove() + resolve(undefined) + return + } + }) + + sendCommand({ cmd: 'GET_STATUS' }) + }) + + return cancelPromise + } + protected async startAuthFlow() { if (this.idCardAuthFlow.isActive) { throw new Error('authentication flow already active') } + try { + await this.cancelPotentiallyAbandonedAuthFlow() + } catch (error) { + return + } + // We return an authentication promise to make it easier to track the state // We remove the callbacks once the error or success is triggered. const authenticationPromise = new Promise((resolve, reject) => {