From 9a52b9a8aebd59b9abe8e6ef762b751677ccf5d0 Mon Sep 17 00:00:00 2001 From: 0xPenryn Date: Tue, 5 Dec 2023 14:53:40 -0600 Subject: [PATCH 1/6] fix: clear result and errorCode on bridge reset solves an issue where reopening the IDKit widget would resubmit the same proof to the callback functions --- packages/core/src/bridge.ts | 2 ++ .../react/src/components/IDKitWidget/States/WorldIDState.tsx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/src/bridge.ts b/packages/core/src/bridge.ts index 211a2105..d4a22c9d 100644 --- a/packages/core/src/bridge.ts +++ b/packages/core/src/bridge.ts @@ -141,6 +141,8 @@ export const useWorldBridgeStore = create((set, get) => ({ set({ iv: null, key: null, + result: null, + errorCode: null, requestId: null, connectorURI: null, verificationState: VerificationState.PreparingClient, diff --git a/packages/react/src/components/IDKitWidget/States/WorldIDState.tsx b/packages/react/src/components/IDKitWidget/States/WorldIDState.tsx index 6ea75f2a..eba6ca28 100644 --- a/packages/react/src/components/IDKitWidget/States/WorldIDState.tsx +++ b/packages/react/src/components/IDKitWidget/States/WorldIDState.tsx @@ -59,7 +59,7 @@ const WorldIDState = () => { if (result) { return handleVerify(result) } - }, [result, reset, handleVerify, verificationState, setStage, errorCode, setErrorState]) + }, [result, handleVerify, verificationState, setStage, errorCode, setErrorState]) return (
From 178daaa5a8f2f871424027283d03b7e7793172be Mon Sep 17 00:00:00 2001 From: 0xPenryn Date: Tue, 5 Dec 2023 14:54:51 -0600 Subject: [PATCH 2/6] feat: error on request timeout throws connection_failed error if pollForUpdates gets a 404 from bridge (meaning request has expired) --- packages/core/src/bridge.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/core/src/bridge.ts b/packages/core/src/bridge.ts index d4a22c9d..4eb5bdce 100644 --- a/packages/core/src/bridge.ts +++ b/packages/core/src/bridge.ts @@ -1,7 +1,7 @@ import { create } from 'zustand' import { buffer_decode } from './lib/utils' +import { AppErrorCodes } from '@/types/bridge' import { VerificationState } from '@/types/bridge' -import type { AppErrorCodes } from '@/types/bridge' import type { ISuccessResult } from '@/types/result' import { encodeAction, generateSignal } from '@/lib/hashing' import { CredentialType, type IDKitConfig } from '@/types/config' @@ -112,6 +112,13 @@ export const useWorldBridgeStore = create((set, get) => ({ const res = await fetch(`${get().bridge_url}/response/${get().requestId}`) + if (!res.ok) { + return set({ + errorCode: AppErrorCodes.ConnectionFailed, + verificationState: VerificationState.Failed, + }) + } + const { response, status } = (await res.json()) as BridgeResponse if (status != ResponseStatus.Completed) { From 90fbff2b19df7b88bc9e782a3bbac6f5b3fd87c9 Mon Sep 17 00:00:00 2001 From: 0xPenryn Date: Tue, 5 Dec 2023 14:55:58 -0600 Subject: [PATCH 3/6] feat: handle errors thrown in handleVerify ensures that handleVerify callbacks are processed async so the promise can reject on thrown errors and display them nicely in IDKit --- packages/react/src/store/idkit.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/store/idkit.ts b/packages/react/src/store/idkit.ts index 85acfa8e..9f1c70ff 100644 --- a/packages/react/src/store/idkit.ts +++ b/packages/react/src/store/idkit.ts @@ -140,7 +140,7 @@ const useIDKitStore = createWithEqualityFn()( handleVerify: (result: ISuccessResult) => { set({ stage: IDKITStage.HOST_APP_VERIFICATION, processing: false }) - Promise.all(Object.values(get().verifyCallbacks).map(cb => cb?.(result))).then( + Promise.all(Object.values(get().verifyCallbacks).map(async cb => cb?.(result))).then( () => { set({ stage: IDKITStage.SUCCESS, result }) From d9681368a59dbfcd7cc963118a1f33359cde9d75 Mon Sep 17 00:00:00 2001 From: 0xPenryn Date: Tue, 5 Dec 2023 15:21:41 -0600 Subject: [PATCH 4/6] feat: ensure returned credentialType is acceptable checks to ensure the credential_type in the proof returned from the bridge is one of the configured credential_types, and displays the relevant error if not this should only happen when manually selecting the wrong credential in the simulator, but good to have anyway --- .../src/components/IDKitWidget/States/WorldIDState.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/react/src/components/IDKitWidget/States/WorldIDState.tsx b/packages/react/src/components/IDKitWidget/States/WorldIDState.tsx index eba6ca28..f5d38812 100644 --- a/packages/react/src/components/IDKitWidget/States/WorldIDState.tsx +++ b/packages/react/src/components/IDKitWidget/States/WorldIDState.tsx @@ -57,9 +57,14 @@ const WorldIDState = () => { } if (result) { + if (!credential_types?.includes(result.credential_type)) { + setStage(IDKITStage.ERROR) + setErrorState({ code: AppErrorCodes.CredentialUnavailable }) + return + } return handleVerify(result) } - }, [result, handleVerify, verificationState, setStage, errorCode, setErrorState]) + }, [result, handleVerify, verificationState, setStage, errorCode, setErrorState, credential_types]) return (
From ac5ecebedb73d911990e04cf7b880609877c0574 Mon Sep 17 00:00:00 2001 From: 0xPenryn Date: Wed, 6 Dec 2023 12:01:26 -0600 Subject: [PATCH 5/6] feat: log error when disallowed credential is returned --- .../react/src/components/IDKitWidget/States/WorldIDState.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react/src/components/IDKitWidget/States/WorldIDState.tsx b/packages/react/src/components/IDKitWidget/States/WorldIDState.tsx index f5d38812..ba451193 100644 --- a/packages/react/src/components/IDKitWidget/States/WorldIDState.tsx +++ b/packages/react/src/components/IDKitWidget/States/WorldIDState.tsx @@ -58,6 +58,9 @@ const WorldIDState = () => { if (result) { if (!credential_types?.includes(result.credential_type)) { + console.error( + 'Credential type returned does not match configured credential_types. This should only happen when manually selecting disallowed credentials in the Worldcoin Simulator.' + ) setStage(IDKITStage.ERROR) setErrorState({ code: AppErrorCodes.CredentialUnavailable }) return From 772b18b6700b398078553a96f1bbcb4c07058f75 Mon Sep 17 00:00:00 2001 From: 0xPenryn Date: Wed, 6 Dec 2023 12:10:30 -0600 Subject: [PATCH 6/6] fix: document `async` in handleVerify callback runner --- packages/react/src/store/idkit.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react/src/store/idkit.ts b/packages/react/src/store/idkit.ts index 9f1c70ff..e36eaa9e 100644 --- a/packages/react/src/store/idkit.ts +++ b/packages/react/src/store/idkit.ts @@ -140,6 +140,9 @@ const useIDKitStore = createWithEqualityFn()( handleVerify: (result: ISuccessResult) => { set({ stage: IDKITStage.HOST_APP_VERIFICATION, processing: false }) + // the `async` added below ensures that we properly handle errors thrown by the callbacks if they are defined as synchronous functions + // without it, if `handleVerify` was a synchronous function and it threw an error, the error would not be caught by the promise chain to be properly displayed in IDKit + // this has no effect on the callbacks if they are defined as asynchronous functions Promise.all(Object.values(get().verifyCallbacks).map(async cb => cb?.(result))).then( () => { set({ stage: IDKITStage.SUCCESS, result })